From e8a260dbc487865624d312f7fade8f6d659637ff Mon Sep 17 00:00:00 2001 From: Yohan Avishke Date: Thu, 6 Feb 2020 18:07:36 +0530 Subject: [PATCH 1/2] Change API to filter devices using a given OS version When syncing devices a value will be generated for each device version. At the API call same method is used to generate a value for the passed OS version then thedevices are filtered using those 2 values. This will still create a similar value but now will use mathematical operations(pow operations) to generate --- .../service/api/ReportManagementService.java | 18 +-- .../impl/ReportManagementServiceImpl.java | 24 ++-- .../exceptions/BadRequestException.java | 46 +++++++ .../report/mgt/ReportManagementService.java | 4 +- .../carbon/device/mgt/core/dao/DeviceDAO.java | 4 +- .../core/dao/impl/AbstractDeviceDAOImpl.java | 103 +------------- .../dao/impl/device/GenericDeviceDAOImpl.java | 121 +++++++++++++++++ .../dao/impl/device/OracleDeviceDAOImpl.java | 126 ++++++++++++------ .../impl/device/PostgreSQLDeviceDAOImpl.java | 110 +++++++++++++++ .../impl/device/SQLServerDeviceDAOImpl.java | 110 +++++++++++++++ .../impl/DeviceInformationManagerImpl.java | 38 ++++++ .../device/mgt/core/report/mgt/Constants.java | 36 +++-- .../mgt/ReportManagementServiceImpl.java | 54 +++++--- .../mgt/core/util/DeviceManagerUtil.java | 87 ++++++++++++ 14 files changed, 681 insertions(+), 200 deletions(-) create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/exceptions/BadRequestException.java diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/ReportManagementService.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/ReportManagementService.java index 6ce1b09403c..aa5424abd3a 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/ReportManagementService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/ReportManagementService.java @@ -313,12 +313,12 @@ public interface ReportManagementService { int limit) throws ReportManagementException; @GET - @Path("expired-devices/{deviceType}") + @Path("/expired-devices/{deviceType}") @ApiOperation( produces = MediaType.APPLICATION_JSON, httpMethod = "GET", - value = "Getting Details of Registered Devices filtered by OS version build date", - notes = "Provides details of devices that have a version build date older than the provided date.", + value = "Getting Details of Registered Devices filtered by OS version", + notes = "Provides details of devices that have a OS version older than the provided version.", tags = "Device Management", extensions = { @Extension(properties = { @@ -337,9 +337,9 @@ public interface ReportManagementService { name = "Content-Type", description = "The content type of the body")}), @ApiResponse( - code = 404, - message = "Not Found. " + - "\n Device type does not exist", + code = 400, + message = "Bad Request. " + + "\n Contents of the request are invalid", response = ErrorResponse.class), @ApiResponse( code = 500, @@ -354,10 +354,10 @@ public interface ReportManagementService { required = true) @PathParam("deviceType") String deviceType, @ApiParam( - name = "osBuildDate", - value = "Minimum OS version build date which is used to filter the devices.", + name = "osVersion", + value = "Minimum OS version which is used to filter the devices.", required = true) - @QueryParam("osBuildDate") Long osBuildDate, + @QueryParam("osVersion") String osVersion, @ApiParam( name = "offset", value = "The starting pagination index for the list of filtered devices.", diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/ReportManagementServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/ReportManagementServiceImpl.java index 331a3bfdd2b..4ecf7b7bd63 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/ReportManagementServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/ReportManagementServiceImpl.java @@ -25,6 +25,7 @@ import org.apache.commons.logging.LogFactory; import org.wso2.carbon.device.mgt.common.Device; import org.wso2.carbon.device.mgt.common.PaginationRequest; import org.wso2.carbon.device.mgt.common.PaginationResult; +import org.wso2.carbon.device.mgt.common.exceptions.BadRequestException; import org.wso2.carbon.device.mgt.common.exceptions.DeviceTypeNotFoundException; import org.wso2.carbon.device.mgt.common.exceptions.ReportManagementException; import org.wso2.carbon.device.mgt.core.report.mgt.Constants; @@ -169,10 +170,10 @@ public class ReportManagementServiceImpl implements ReportManagementService { } @GET - @Path("expired-devices/{deviceType}") + @Path("/expired-devices/{deviceType}") @Override public Response getExpiredDevicesByOSVersion(@PathParam("deviceType") String deviceType, - @QueryParam("osBuildDate") Long osBuildDate, + @QueryParam("osVersion") String osVersion, @DefaultValue("0") @QueryParam("offset") int offset, @DefaultValue("5") @@ -180,20 +181,23 @@ public class ReportManagementServiceImpl implements ReportManagementService { try { PaginationRequest request = new PaginationRequest(offset, limit); request.setDeviceType(deviceType); - request.setProperty(Constants.OS_BUILD_DATE, osBuildDate); + request.setProperty(Constants.OS_VERSION, osVersion); PaginationResult paginationResult = DeviceMgtAPIUtils .getReportManagementService() .getDevicesExpiredByOSVersion(request); - return Response.status(Response.Status.OK).entity(paginationResult).build(); - } catch (DeviceTypeNotFoundException e) { - String msg = "Error occurred while retrieving devices list. Device type: " + deviceType + - "is not valid"; - log.error(msg); - return Response.status(Response.Status.NOT_FOUND).entity(msg).build(); + DeviceList devices = new DeviceList(); + devices.setList((List) paginationResult.getData()); + devices.setCount(paginationResult.getRecordsTotal()); + + return Response.status(Response.Status.OK).entity(devices).build(); + } catch (BadRequestException e) { + String msg = "Error occurred while validating device type or the OS version."; + log.error(msg, e); + return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); } catch (ReportManagementException e) { - String msg = "Error occurred while retrieving devices list with out-dated OS build versions"; + String msg = "Error occurred while retrieving list of devices with out-dated OS versions."; log.error(msg, e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/exceptions/BadRequestException.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/exceptions/BadRequestException.java new file mode 100644 index 00000000000..5b1b26e92e9 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/exceptions/BadRequestException.java @@ -0,0 +1,46 @@ +/* + * + * Copyright (c) 2020, Entgra (pvt) Ltd. (http://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.exceptions; + +public class BadRequestException extends Exception { + private static final long serialVersionUID = 2304023531260840549L; + + public BadRequestException() { + super(); + } + + public BadRequestException(String msg) { + super(msg); + } + + public BadRequestException(Throwable cause) { + super(cause); + } + + public BadRequestException(String msg, Exception nestedEx) { + super(msg, nestedEx); + } + + public BadRequestException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/report/mgt/ReportManagementService.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/report/mgt/ReportManagementService.java index 6e001fd73bf..6216c3afb25 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/report/mgt/ReportManagementService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/report/mgt/ReportManagementService.java @@ -21,6 +21,7 @@ import com.google.gson.JsonObject; import org.wso2.carbon.device.mgt.common.PaginationRequest; import org.wso2.carbon.device.mgt.common.PaginationResult; import org.wso2.carbon.device.mgt.common.app.mgt.ApplicationManagementException; +import org.wso2.carbon.device.mgt.common.exceptions.BadRequestException; import org.wso2.carbon.device.mgt.common.exceptions.DeviceTypeNotFoundException; import org.wso2.carbon.device.mgt.common.exceptions.ReportManagementException; @@ -56,10 +57,9 @@ public interface ReportManagementService { * @param request {@link PaginationRequest} * @return {@link PaginationResult} * @throws ReportManagementException Might occur during the business logic or building database query - * @throws DeviceTypeNotFoundException Might occur while validating the device type */ PaginationResult getDevicesExpiredByOSVersion(PaginationRequest request) - throws ReportManagementException, DeviceTypeNotFoundException; + throws ReportManagementException, BadRequestException; /** * Get a paginated list of devices which is filtered by given encryption status diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceDAO.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceDAO.java index 5ba8cc956f2..4eb94b606b3 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceDAO.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceDAO.java @@ -637,12 +637,12 @@ public interface DeviceDAO { * Count the number of devices older than the given OS version of a device type * * @param deviceType Device type name - * @param osBuildDate BUild date off the current OS version + * @param osValue Generated value for the OS version * @param tenantId Id of the current tenant. * @return {@link Integer} * @throws DeviceManagementDAOException Thrown if error occurs while database transactions */ - int getCountOfDeviceExpiredByOSVersion(String deviceType, long osBuildDate, int tenantId) + int getCountOfDeviceExpiredByOSVersion(String deviceType, Long osValue, int tenantId) throws DeviceManagementDAOException; /** diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractDeviceDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractDeviceDAOImpl.java index f0d78aef013..0279c654bf2 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractDeviceDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractDeviceDAOImpl.java @@ -1915,108 +1915,7 @@ public abstract class AbstractDeviceDAOImpl implements DeviceDAO { throw new DeviceManagementDAOException(msg, e); } } - - @Override - public List getDevicesExpiredByOSVersion(PaginationRequest request, int tenantId) - throws DeviceManagementDAOException { - try { - Long osBuildDate = (Long) request.getProperty(Constants.OS_BUILD_DATE); - Connection conn = getConnection(); - String sql = "SELECT " + - "dt.NAME AS DEVICE_TYPE, " + - "d.ID AS DEVICE_ID, " + - "d.NAME AS DEVICE_NAME, " + - "d.DESCRIPTION, " + - "d.DEVICE_IDENTIFICATION, " + - "dd.OS_VERSION, " + - "dd.OS_BUILD_DATE, " + - "e.ID AS ENROLMENT_ID, " + - "e.OWNER, " + - "e.OWNERSHIP, " + - "e.STATUS, " + - "e.DATE_OF_LAST_UPDATE, " + - "e.DATE_OF_ENROLMENT " + - "FROM DM_DEVICE d, " + - "DM_DEVICE_DETAIL dd, " + - "DM_ENROLMENT e, " + - "(SELECT ID, NAME " + - "FROM DM_DEVICE_TYPE " + - "WHERE NAME = ? " + - "AND PROVIDER_TENANT_ID = ?) dt " + - "WHERE dt.ID = d.DEVICE_TYPE_ID " + - "AND d.ID = e.DEVICE_ID " + - "AND d.ID = dd.DEVICE_ID " + - "AND dd.OS_BUILD_DATE < ? " + - "LIMIT ? OFFSET ?"; - - try (PreparedStatement ps = conn.prepareStatement(sql)) { - int paramIDx = 1; - ps.setString(paramIDx++, request.getDeviceType()); - ps.setInt(paramIDx++, tenantId); - ps.setLong(paramIDx++, osBuildDate); - ps.setInt(paramIDx++, request.getRowCount()); - ps.setInt(paramIDx, request.getStartIndex()); - - try (ResultSet rs = ps.executeQuery()) { - List devices = new ArrayList<>(); - DeviceInfo deviceInfo = new DeviceInfo(); - while (rs.next()) { - Device device = DeviceManagementDAOUtil.loadDevice(rs); - deviceInfo.setOsVersion(rs.getString(Constants.OS_VERSION)); - deviceInfo.setOsBuildDate(rs.getString(Constants.OS_BUILD_DATE)); - device.setDeviceInfo(deviceInfo); - devices.add(device); - } - return devices; - } - } - } catch (SQLException e) { - String msg = "Error occurred while building or executing queries to retrieve information " + - "of devices with an older OS build date"; - log.error(msg, e); - throw new DeviceManagementDAOException(msg, e); - } - } - - @Override - public int getCountOfDeviceExpiredByOSVersion(String deviceType, long osBuildDate, int tenantId) - throws DeviceManagementDAOException { - try { - Connection conn = getConnection(); - String sql = "SELECT " + - "COUNT(dd.DEVICE_ID) AS DEVICE_COUNT " + - "FROM DM_DEVICE d, " + - "DM_DEVICE_DETAIL dd, " + - "(SELECT ID " + - "FROM DM_DEVICE_TYPE " + - "WHERE NAME = ? " + - "AND PROVIDER_TENANT_ID = ?) dt " + - "WHERE d.DEVICE_TYPE_ID = dt.ID " + - "AND d.ID = dd.DEVICE_ID " + - "AND dd.OS_BUILD_DATE < ?"; - - try (PreparedStatement ps = conn.prepareStatement(sql)) { - int paramIdx = 1; - ps.setString(paramIdx++, deviceType); - ps.setInt(paramIdx++, tenantId); - ps.setLong(paramIdx, osBuildDate); - - try (ResultSet rs = ps.executeQuery()) { - int deviceCount = 0; - if (rs.next()) { - deviceCount = rs.getInt("DEVICE_COUNT"); - } - return deviceCount; - } - } - } catch (SQLException e) { - String msg = "Error occurred while building or executing queries to retrieve the count " + - "of devices with an older OS build date"; - log.error(msg, e); - throw new DeviceManagementDAOException(msg, e); - } - } - + @Override public List getAppNotInstalledDevices( PaginationRequest request, int tenantId, String packageName, String version) diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/GenericDeviceDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/GenericDeviceDAOImpl.java index 471929dc128..01de7ca32b0 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/GenericDeviceDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/GenericDeviceDAOImpl.java @@ -23,11 +23,14 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.device.mgt.common.Count; import org.wso2.carbon.device.mgt.common.Device; +import org.wso2.carbon.device.mgt.common.DeviceManagementConstants; import org.wso2.carbon.device.mgt.common.PaginationRequest; +import org.wso2.carbon.device.mgt.common.device.details.DeviceInfo; import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOException; import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOFactory; import org.wso2.carbon.device.mgt.core.dao.impl.AbstractDeviceDAOImpl; import org.wso2.carbon.device.mgt.core.dao.util.DeviceManagementDAOUtil; +import org.wso2.carbon.device.mgt.core.report.mgt.Constants; import java.sql.Connection; import java.sql.PreparedStatement; @@ -858,6 +861,124 @@ public class GenericDeviceDAOImpl extends AbstractDeviceDAOImpl { } } + @Override + public List getDevicesExpiredByOSVersion(PaginationRequest request, int tenantId) + throws DeviceManagementDAOException { + try { + Long osValue = (Long) request.getProperty(Constants.OS_VALUE); + Connection conn = getConnection(); + String dataSourceType = conn.getMetaData().getDatabaseProductName(); + String sql="SELECT " + + "d1.DEVICE_TYPE, " + + "d1.DEVICE_ID, " + + "d1.DEVICE_NAME, " + + "d1.DESCRIPTION, " + + "d1.DEVICE_IDENTIFICATION, " + + "ddd.OS_VERSION, " + + "e.ID AS ENROLMENT_ID, " + + "e.OWNER, " + + "e.OWNERSHIP, " + + "e.STATUS, " + + "e.DATE_OF_LAST_UPDATE, " + + "e.DATE_OF_ENROLMENT " + + "FROM DM_DEVICE_INFO ddi," + + "DM_DEVICE_DETAIL ddd, " + + "DM_ENROLMENT e, " + + "(SELECT dt.NAME AS DEVICE_TYPE, " + + "d.ID AS DEVICE_ID, " + + "d.NAME AS DEVICE_NAME, " + + "DESCRIPTION, " + + "DEVICE_IDENTIFICATION " + + "FROM DM_DEVICE_TYPE dt, " + + "DM_DEVICE d " + + "WHERE dt.NAME = ? " + + "AND PROVIDER_TENANT_ID = ? " + + "AND dt.ID = d.DEVICE_TYPE_ID " + + ") d1 " + + "WHERE d1.DEVICE_ID = e.DEVICE_ID " + + "AND d1.DEVICE_ID = ddi.DEVICE_ID " + + "AND ddi.KEY_FIELD = ? "; + if (dataSourceType.contains(DeviceManagementConstants.DataBaseTypes.DB_TYPE_H2)) { + sql += "AND CAST( ddi.VALUE_FIELD AS BIGINT ) < ? "; + } else if (dataSourceType.contains(DeviceManagementConstants.DataBaseTypes.DB_TYPE_MYSQL)) { + sql += "AND CAST( ddi.VALUE_FIELD AS UNSIGNED ) < ? "; + } + sql += "LIMIT ? OFFSET ?"; + + try (PreparedStatement ps = conn.prepareStatement(sql)) { + ps.setString(1, request.getDeviceType()); + ps.setInt(2, tenantId); + ps.setString(3, Constants.OS_VALUE); + ps.setLong(4, osValue); + ps.setInt(5, request.getRowCount()); + ps.setInt(6, request.getStartIndex()); + + try (ResultSet rs = ps.executeQuery()) { + List devices = new ArrayList<>(); + while (rs.next()) { + Device device = DeviceManagementDAOUtil.loadDevice(rs); + DeviceInfo deviceInfo = new DeviceInfo(); + deviceInfo.setOsVersion(rs.getString("OS_VERSION")); + device.setDeviceInfo(deviceInfo); + devices.add(device); + } + return devices; + } + } + } catch (SQLException e) { + String msg = "Error occurred while building or executing queries to retrieve information " + + "of devices with an older OS build date"; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + @Override + public int getCountOfDeviceExpiredByOSVersion(String deviceType, Long osValue, int tenantId) + throws DeviceManagementDAOException { + try { + Connection conn = getConnection(); + String dataSourceType = conn.getMetaData().getDatabaseProductName(); + String sql = "SELECT " + + "COUNT(ddi.DEVICE_ID) AS DEVICE_COUNT " + + "FROM DM_DEVICE_INFO ddi, " + + "(SELECT d.ID AS DEVICE_ID " + + "FROM DM_DEVICE_TYPE dt, " + + "DM_DEVICE d " + + "WHERE dt.NAME = ? " + + "AND PROVIDER_TENANT_ID = ? " + + "AND dt.ID = d.DEVICE_TYPE_ID " + + ") d1 " + + "WHERE d1.DEVICE_ID = ddi.DEVICE_ID " + + "AND ddi.KEY_FIELD = ? "; + if (dataSourceType.contains(DeviceManagementConstants.DataBaseTypes.DB_TYPE_H2)) { + sql += "AND CAST( ddi.VALUE_FIELD AS BIGINT ) < ? "; + } else if (dataSourceType.contains(DeviceManagementConstants.DataBaseTypes.DB_TYPE_MYSQL)) { + sql += "AND CAST( ddi.VALUE_FIELD AS UNSIGNED ) < ? "; + } + + try (PreparedStatement ps = conn.prepareStatement(sql)) { + ps.setString(1, deviceType); + ps.setInt(2, tenantId); + ps.setString(3, Constants.OS_VALUE); + ps.setLong(4, osValue); + + try (ResultSet rs = ps.executeQuery()) { + int deviceCount = 0; + if (rs.next()) { + deviceCount = rs.getInt("DEVICE_COUNT"); + } + return deviceCount; + } + } + } catch (SQLException e) { + String msg = "Error occurred while building or executing queries to retrieve the count " + + "of devices with an older OS build date"; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + private Connection getConnection() throws SQLException { return DeviceManagementDAOFactory.getConnection(); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/OracleDeviceDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/OracleDeviceDAOImpl.java index 37a64568b6c..695f1b9ce87 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/OracleDeviceDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/OracleDeviceDAOImpl.java @@ -834,52 +834,57 @@ public class OracleDeviceDAOImpl extends AbstractDeviceDAOImpl { public List getDevicesExpiredByOSVersion(PaginationRequest request, int tenantId) throws DeviceManagementDAOException { try { - Long osBuildDate = (Long) request.getProperty(Constants.OS_BUILD_DATE); + Long osValue = (Long) request.getProperty(Constants.OS_VALUE); Connection conn = getConnection(); - String sql = "SELECT " + - "dt.NAME AS DEVICE_TYPE, " + - "d.ID AS DEVICE_ID, " + - "d.NAME AS DEVICE_NAME, " + - "d.DESCRIPTION, " + - "d.DEVICE_IDENTIFICATION, " + - "dd.OS_VERSION, " + - "dd.OS_BUILD_DATE, " + - "e.ID AS ENROLMENT_ID, " + - "e.OWNER, " + - "e.OWNERSHIP, " + - "e.STATUS, " + - "e.DATE_OF_LAST_UPDATE, " + - "e.DATE_OF_ENROLMENT " + - "FROM DM_DEVICE d, " + - "DM_DEVICE_DETAIL dd, " + - "DM_ENROLMENT e, " + - "(SELECT ID, NAME " + - "FROM DM_DEVICE_TYPE " + - "WHERE NAME = ? " + - "AND PROVIDER_TENANT_ID = ?) dt " + - "WHERE dt.ID = d.DEVICE_TYPE_ID " + - "AND d.ID = e.DEVICE_ID " + - "AND d.ID = dd.DEVICE_ID " + - "AND dd.OS_BUILD_DATE < ? " + - "ORDER BY ENROLMENT_ID " + - "OFFSET ? ROWS " + - "FETCH NEXT ? ROWS ONLY"; + String sql="SELECT " + + "d1.DEVICE_TYPE, " + + "d1.DEVICE_ID, " + + "d1.DEVICE_NAME, " + + "d1.DESCRIPTION, " + + "d1.DEVICE_IDENTIFICATION, " + + "ddd.OS_VERSION, " + + "e.ID AS ENROLMENT_ID, " + + "e.OWNER, " + + "e.OWNERSHIP, " + + "e.STATUS, " + + "e.DATE_OF_LAST_UPDATE, " + + "e.DATE_OF_ENROLMENT " + + "FROM DM_DEVICE_INFO ddi, " + + "DM_DEVICE_DETAIL ddd, " + + "DM_ENROLMENT e, " + + "(SELECT dt.NAME AS DEVICE_TYPE, " + + "d.ID AS DEVICE_ID, " + + "d.NAME AS DEVICE_NAME, " + + "DESCRIPTION, " + + "DEVICE_IDENTIFICATION " + + " FROM DM_DEVICE_TYPE dt, " + + "DM_DEVICE d " + + "WHERE dt.NAME = ? " + + "AND PROVIDER_TENANT_ID = ? " + + "AND dt.ID = d.DEVICE_TYPE_ID " + + ") d1 " + + "WHERE d1.DEVICE_ID = e.DEVICE_ID " + + "AND d1.DEVICE_ID = ddi.DEVICE_ID " + + "AND ddi.KEY_FIELD = ? " + + "AND CAST( ddi.VALUE_FIELD AS BIGINT ) < ? " + + "ORDER BY ENROLMENT_ID " + + "OFFSET ? ROWS " + + "FETCH NEXT ? ROWS ONLY"; try (PreparedStatement ps = conn.prepareStatement(sql)) { - int paramIDx = 1; - ps.setString(paramIDx++, request.getDeviceType()); - ps.setInt(paramIDx++, tenantId); - ps.setLong(paramIDx++, osBuildDate); - ps.setInt(paramIDx++, request.getStartIndex()); - ps.setInt(paramIDx, request.getRowCount()); + ps.setString(1, request.getDeviceType()); + ps.setInt(2, tenantId); + ps.setString(3, Constants.OS_VALUE); + ps.setLong(4, osValue); + ps.setInt(5, request.getStartIndex()); + ps.setInt(6, request.getRowCount()); try (ResultSet rs = ps.executeQuery()) { List devices = new ArrayList<>(); - DeviceInfo deviceInfo = new DeviceInfo(); while (rs.next()) { Device device = DeviceManagementDAOUtil.loadDevice(rs); - deviceInfo.setOsVersion(rs.getString(Constants.OS_VERSION)); - deviceInfo.setOsBuildDate(rs.getString(Constants.OS_BUILD_DATE)); + DeviceInfo deviceInfo = new DeviceInfo(); + deviceInfo.setOsVersion(rs.getString("OS_VERSION")); device.setDeviceInfo(deviceInfo); devices.add(device); } @@ -887,8 +892,49 @@ public class OracleDeviceDAOImpl extends AbstractDeviceDAOImpl { } } } catch (SQLException e) { - String msg = "Error occurred while retrieving information of devices with an older OS date " + - "than the minimum date"; + String msg = "Error occurred while building or executing queries to retrieve information " + + "of devices with an older OS build date"; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + @Override + public int getCountOfDeviceExpiredByOSVersion(String deviceType, Long osValue, int tenantId) + throws DeviceManagementDAOException { + try { + Connection conn = getConnection(); + String sql = "SELECT " + + "COUNT(ddi.DEVICE_ID) AS DEVICE_COUNT " + + "FROM DM_DEVICE_INFO ddi, " + + "(SELECT d.ID AS DEVICE_ID " + + "FROM DM_DEVICE_TYPE dt, " + + "DM_DEVICE d " + + "WHERE dt.NAME = ? " + + "AND PROVIDER_TENANT_ID = ? " + + "AND dt.ID = d.DEVICE_TYPE_ID " + + ") d1 " + + "WHERE d1.DEVICE_ID = ddi.DEVICE_ID " + + "AND ddi.KEY_FIELD = ? " + + "AND CAST( ddi.VALUE_FIELD AS BIGINT ) < ?"; + + try (PreparedStatement ps = conn.prepareStatement(sql)) { + ps.setString(1, deviceType); + ps.setInt(2, tenantId); + ps.setString(3, Constants.OS_VALUE); + ps.setLong(4, osValue); + + try (ResultSet rs = ps.executeQuery()) { + int deviceCount = 0; + if (rs.next()) { + deviceCount = rs.getInt("DEVICE_COUNT"); + } + return deviceCount; + } + } + } catch (SQLException e) { + String msg = "Error occurred while building or executing queries to retrieve the count " + + "of devices with an older OS build date"; log.error(msg, e); throw new DeviceManagementDAOException(msg, e); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/PostgreSQLDeviceDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/PostgreSQLDeviceDAOImpl.java index 5df5f823bb8..8275c7691fd 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/PostgreSQLDeviceDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/PostgreSQLDeviceDAOImpl.java @@ -24,10 +24,12 @@ import org.apache.commons.logging.LogFactory; import org.wso2.carbon.device.mgt.common.Count; import org.wso2.carbon.device.mgt.common.Device; import org.wso2.carbon.device.mgt.common.PaginationRequest; +import org.wso2.carbon.device.mgt.common.device.details.DeviceInfo; import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOException; import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOFactory; import org.wso2.carbon.device.mgt.core.dao.impl.AbstractDeviceDAOImpl; import org.wso2.carbon.device.mgt.core.dao.util.DeviceManagementDAOUtil; +import org.wso2.carbon.device.mgt.core.report.mgt.Constants; import java.sql.Connection; import java.sql.PreparedStatement; @@ -814,6 +816,114 @@ public class PostgreSQLDeviceDAOImpl extends AbstractDeviceDAOImpl { } } + @Override + public List getDevicesExpiredByOSVersion(PaginationRequest request, int tenantId) + throws DeviceManagementDAOException { + try { + Long osValue = (Long) request.getProperty(Constants.OS_VALUE); + Connection conn = getConnection(); + String sql="SELECT " + + "d1.DEVICE_TYPE, " + + "d1.DEVICE_ID, " + + "d1.DEVICE_NAME, " + + "d1.DESCRIPTION, " + + "d1.DEVICE_IDENTIFICATION, " + + "ddd.OS_VERSION, " + + "e.ID AS ENROLMENT_ID, " + + "e.OWNER, " + + "e.OWNERSHIP, " + + "e.STATUS, " + + "e.DATE_OF_LAST_UPDATE, " + + "e.DATE_OF_ENROLMENT " + + "FROM DM_DEVICE_INFO ddi, " + + "DM_DEVICE_DETAIL ddd, " + + "DM_ENROLMENT e, " + + "(SELECT dt.NAME AS DEVICE_TYPE, " + + "d.ID AS DEVICE_ID, " + + "d.NAME AS DEVICE_NAME, " + + "DESCRIPTION, " + + "DEVICE_IDENTIFICATION " + + " FROM DM_DEVICE_TYPE dt, " + + "DM_DEVICE d " + + "WHERE dt.NAME = ? " + + "AND PROVIDER_TENANT_ID = ? " + + "AND dt.ID = d.DEVICE_TYPE_ID " + + ") d1 " + + "WHERE d1.DEVICE_ID = e.DEVICE_ID " + + "AND d1.DEVICE_ID = ddi.DEVICE_ID " + + "AND ddi.KEY_FIELD = ? " + + "AND CAST( ddi.VALUE_FIELD AS BIGINT ) < ? " + + "LIMIT ? OFFSET ?"; + + try (PreparedStatement ps = conn.prepareStatement(sql)) { + ps.setString(1, request.getDeviceType()); + ps.setInt(2, tenantId); + ps.setString(3, Constants.OS_VALUE); + ps.setLong(4, osValue); + ps.setInt(5, request.getRowCount()); + ps.setInt(6, request.getStartIndex()); + + try (ResultSet rs = ps.executeQuery()) { + List devices = new ArrayList<>(); + while (rs.next()) { + Device device = DeviceManagementDAOUtil.loadDevice(rs); + DeviceInfo deviceInfo = new DeviceInfo(); + deviceInfo.setOsVersion(rs.getString("OS_VERSION")); + device.setDeviceInfo(deviceInfo); + devices.add(device); + } + return devices; + } + } + } catch (SQLException e) { + String msg = "Error occurred while building or executing queries to retrieve information " + + "of devices with an older OS build date"; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + @Override + public int getCountOfDeviceExpiredByOSVersion(String deviceType, Long osValue, int tenantId) + throws DeviceManagementDAOException { + try { + Connection conn = getConnection(); + String sql = "SELECT " + + "COUNT(ddi.DEVICE_ID) AS DEVICE_COUNT " + + "FROM DM_DEVICE_INFO ddi, " + + "(SELECT d.ID AS DEVICE_ID " + + "FROM DM_DEVICE_TYPE dt, " + + "DM_DEVICE d " + + "WHERE dt.NAME = ? " + + "AND PROVIDER_TENANT_ID = ? " + + "AND dt.ID = d.DEVICE_TYPE_ID " + + ") d1 " + + "WHERE d1.DEVICE_ID = ddi.DEVICE_ID " + + "AND ddi.KEY_FIELD = ? " + + "AND CAST( ddi.VALUE_FIELD AS BIGINT ) < ?"; + + try (PreparedStatement ps = conn.prepareStatement(sql)) { + ps.setString(1, deviceType); + ps.setInt(2, tenantId); + ps.setString(3, Constants.OS_VALUE); + ps.setLong(4, osValue); + + try (ResultSet rs = ps.executeQuery()) { + int deviceCount = 0; + if (rs.next()) { + deviceCount = rs.getInt("DEVICE_COUNT"); + } + return deviceCount; + } + } + } catch (SQLException e) { + String msg = "Error occurred while building or executing queries to retrieve the count " + + "of devices with an older OS build date"; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + private Connection getConnection() throws SQLException { return DeviceManagementDAOFactory.getConnection(); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/SQLServerDeviceDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/SQLServerDeviceDAOImpl.java index 299917edd2c..657e8d7a5c3 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/SQLServerDeviceDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/SQLServerDeviceDAOImpl.java @@ -24,12 +24,14 @@ import org.apache.commons.logging.LogFactory; import org.wso2.carbon.device.mgt.common.Count; import org.wso2.carbon.device.mgt.common.Device; import org.wso2.carbon.device.mgt.common.PaginationRequest; +import org.wso2.carbon.device.mgt.common.device.details.DeviceInfo; import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOException; import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOFactory; import org.wso2.carbon.device.mgt.core.dao.impl.AbstractDeviceDAOImpl; import org.wso2.carbon.device.mgt.core.dao.util.DeviceManagementDAOUtil; import org.wso2.carbon.device.mgt.core.geo.GeoCluster; import org.wso2.carbon.device.mgt.core.geo.geoHash.GeoCoordinate; +import org.wso2.carbon.device.mgt.core.report.mgt.Constants; import java.sql.Connection; import java.sql.PreparedStatement; @@ -630,6 +632,114 @@ public class SQLServerDeviceDAOImpl extends AbstractDeviceDAOImpl { } } + @Override + public List getDevicesExpiredByOSVersion(PaginationRequest request, int tenantId) + throws DeviceManagementDAOException { + try { + Long osValue = (Long) request.getProperty(Constants.OS_VALUE); + Connection conn = getConnection(); + String sql="SELECT " + + "d1.DEVICE_TYPE, " + + "d1.DEVICE_ID, " + + "d1.DEVICE_NAME, " + + "d1.DESCRIPTION, " + + "d1.DEVICE_IDENTIFICATION, " + + "ddd.OS_VERSION, " + + "e.ID AS ENROLMENT_ID, " + + "e.OWNER, " + + "e.OWNERSHIP, " + + "e.STATUS, " + + "e.DATE_OF_LAST_UPDATE, " + + "e.DATE_OF_ENROLMENT " + + "FROM DM_DEVICE_INFO ddi, " + + "DM_DEVICE_DETAIL ddd, " + + "DM_ENROLMENT e, " + + "(SELECT dt.NAME AS DEVICE_TYPE, " + + "d.ID AS DEVICE_ID, " + + "d.NAME AS DEVICE_NAME, " + + "DESCRIPTION, " + + "DEVICE_IDENTIFICATION " + + " FROM DM_DEVICE_TYPE dt, " + + "DM_DEVICE d " + + "WHERE dt.NAME = ? " + + "AND PROVIDER_TENANT_ID = ? " + + "AND dt.ID = d.DEVICE_TYPE_ID " + + ") d1 " + + "WHERE d1.DEVICE_ID = e.DEVICE_ID " + + "AND d1.DEVICE_ID = ddi.DEVICE_ID " + + "AND ddi.KEY_FIELD = ? " + + "AND CAST( ddi.VALUE_FIELD AS BIGINT ) < ? " + + "LIMIT ? OFFSET ?"; + + try (PreparedStatement ps = conn.prepareStatement(sql)) { + ps.setString(1, request.getDeviceType()); + ps.setInt(2, tenantId); + ps.setString(3, Constants.OS_VALUE); + ps.setLong(4, osValue); + ps.setInt(5, request.getRowCount()); + ps.setInt(6, request.getStartIndex()); + + try (ResultSet rs = ps.executeQuery()) { + List devices = new ArrayList<>(); + while (rs.next()) { + Device device = DeviceManagementDAOUtil.loadDevice(rs); + DeviceInfo deviceInfo = new DeviceInfo(); + deviceInfo.setOsVersion(rs.getString("OS_VERSION")); + device.setDeviceInfo(deviceInfo); + devices.add(device); + } + return devices; + } + } + } catch (SQLException e) { + String msg = "Error occurred while building or executing queries to retrieve information " + + "of devices with an older OS build date"; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + @Override + public int getCountOfDeviceExpiredByOSVersion(String deviceType, Long osValue, int tenantId) + throws DeviceManagementDAOException { + try { + Connection conn = getConnection(); + String sql = "SELECT " + + "COUNT(ddi.DEVICE_ID) AS DEVICE_COUNT " + + "FROM DM_DEVICE_INFO ddi, " + + "(SELECT d.ID AS DEVICE_ID " + + "FROM DM_DEVICE_TYPE dt, " + + "DM_DEVICE d " + + "WHERE dt.NAME = ? " + + "AND PROVIDER_TENANT_ID = ? " + + "AND dt.ID = d.DEVICE_TYPE_ID " + + ") d1 " + + "WHERE d1.DEVICE_ID = ddi.DEVICE_ID " + + "AND ddi.KEY_FIELD = ? " + + "AND CAST( ddi.VALUE_FIELD AS BIGINT ) < ?"; + + try (PreparedStatement ps = conn.prepareStatement(sql)) { + ps.setString(1, deviceType); + ps.setInt(2, tenantId); + ps.setString(3, Constants.OS_VALUE); + ps.setLong(4, osValue); + + try (ResultSet rs = ps.executeQuery()) { + int deviceCount = 0; + if (rs.next()) { + deviceCount = rs.getInt("DEVICE_COUNT"); + } + return deviceCount; + } + } + } catch (SQLException e) { + String msg = "Error occurred while building or executing queries to retrieve the count " + + "of devices with an older OS build date"; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + private Connection getConnection() throws SQLException { return DeviceManagementDAOFactory.getConnection(); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/device/details/mgt/impl/DeviceInformationManagerImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/device/details/mgt/impl/DeviceInformationManagerImpl.java index 67360baf900..c6c5e9f270b 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/device/details/mgt/impl/DeviceInformationManagerImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/device/details/mgt/impl/DeviceInformationManagerImpl.java @@ -18,6 +18,7 @@ package org.wso2.carbon.device.mgt.core.device.details.mgt.impl; +import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.context.CarbonContext; @@ -39,6 +40,7 @@ import org.wso2.carbon.device.mgt.core.device.details.mgt.DeviceInformationManag import org.wso2.carbon.device.mgt.core.device.details.mgt.dao.DeviceDetailsDAO; import org.wso2.carbon.device.mgt.core.device.details.mgt.dao.DeviceDetailsMgtDAOException; import org.wso2.carbon.device.mgt.core.internal.DeviceManagementDataHolder; +import org.wso2.carbon.device.mgt.core.report.mgt.Constants; import org.wso2.carbon.device.mgt.core.util.DeviceManagerUtil; import org.wso2.carbon.device.mgt.core.util.HttpReportingUtil; @@ -98,6 +100,8 @@ public class DeviceInformationManagerImpl implements DeviceInformationManager { } else { Map updatableProps = new HashMap<>(); Map injectableProps = new HashMap<>(); + // generate a default value depending on the devices OS version + addOSVersionValue(device, newDeviceInfo); for (String key : newDeviceInfo.getDeviceDetailsMap().keySet()) { if (previousDeviceProperties.containsKey(key)) { updatableProps.put(key, newDeviceInfo.getDeviceDetailsMap().get(key)); @@ -420,5 +424,39 @@ public class DeviceInformationManagerImpl implements DeviceInformationManager { return newDeviceInfo; } + /** + * Generate and add a value depending on the device's OS version included in device info + * + * @param device device data + * @param newDeviceInfo device info data + */ + private void addOSVersionValue(Device device, DeviceInfo newDeviceInfo) { + String deviceTypeName = device.getType(); + if (StringUtils.isBlank(device.getType())) { + if (log.isDebugEnabled()) { + log.debug("Unable to generate a OS version value for device type: " + + deviceTypeName + ". Device type cannot be null or empty"); + } + } else { + if (!deviceTypeName.equals("android") && !deviceTypeName.equals("ios")) { + if (log.isDebugEnabled()) { + log.debug("Unable to generate a OS version value for device type: " + + deviceTypeName + ". OS version value is only generatable for " + + "android and ios"); + } + } else { + String osVersion = newDeviceInfo.getOsVersion(); + String osValue = String.valueOf(DeviceManagerUtil.generateOSVersionValue(osVersion)); + if (StringUtils.isBlank(osValue)) { + if (log.isDebugEnabled()) { + log.debug("Unable to generate a OS version value for OS version: " + + osVersion + " for device type: " + deviceTypeName); + } + } else { + newDeviceInfo.getDeviceDetailsMap().put(Constants.OS_VALUE, osValue); + } + } + } + } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/report/mgt/Constants.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/report/mgt/Constants.java index 49db80418bc..4f5406e5605 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/report/mgt/Constants.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/report/mgt/Constants.java @@ -1,27 +1,35 @@ /* - * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * - * WSO2 Inc. 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 + * Copyright (c) 2020, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved. * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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. * - * 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.core.report.mgt; public class Constants { - -// device properties + // device types + public static final String ANDROID = "android"; + public static final String IOS = "ios"; + // device properties public static final String OS_BUILD_DATE = "OS_BUILD_DATE"; public static final String OS_VERSION = "OS_VERSION"; + public static final String OS_VALUE = "OS_VALUE"; + // OS version value generating properties + public static final int NUM_OF_OS_VERSION_DIGITS= 5; + public static final int NUM_OF_OS_VERSION_POSITIONS = 3; } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/report/mgt/ReportManagementServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/report/mgt/ReportManagementServiceImpl.java index 4c097906555..ce63ff965d7 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/report/mgt/ReportManagementServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/report/mgt/ReportManagementServiceImpl.java @@ -23,6 +23,9 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.device.mgt.common.Count; import org.wso2.carbon.device.mgt.common.Device; +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.exceptions.BadRequestException; import org.wso2.carbon.device.mgt.common.exceptions.DeviceManagementException; import org.wso2.carbon.device.mgt.common.PaginationRequest; import org.wso2.carbon.device.mgt.common.PaginationResult; @@ -157,46 +160,55 @@ public class ReportManagementServiceImpl implements ReportManagementService { @Override public PaginationResult getDevicesExpiredByOSVersion(PaginationRequest request) - throws ReportManagementException, DeviceTypeNotFoundException { + throws ReportManagementException, BadRequestException { if (request == null || StringUtils.isBlank(request.getDeviceType()) || - !request.getProperties().containsKey(Constants.OS_BUILD_DATE) || - (Long) request.getProperty(Constants.OS_BUILD_DATE) == 0) { - + request.getProperties() == null || + !request.getProperties().containsKey(Constants.OS_VERSION) || + StringUtils.isBlank((String) request.getProperty(Constants.OS_VERSION))) { String msg = "Error Invalid data received from the request.\n" + - "osBuildDate cannot be null or 0 and device type cannot be null or empty"; + "osVersion and device type cannot be null or empty."; log.error(msg); - throw new ReportManagementException(msg); + throw new BadRequestException(msg); } + + String deviceType = request.getDeviceType(); + if (!deviceType.equals(Constants.ANDROID) && !deviceType.equals(Constants.IOS)) { + String msg = "Error Invalid device type:" + deviceType + " received. Valid device types " + + "are android and ios."; + log.error(msg); + throw new BadRequestException(msg); + } + try { int tenantId = DeviceManagementDAOUtil.getTenantId(); - String deviceType = request.getDeviceType(); PaginationResult paginationResult = new PaginationResult(); - DeviceManagerUtil.validateDeviceListPageSize(request); - DeviceType deviceTypeObj = DeviceManagerUtil.getDeviceType( - deviceType, tenantId); - if (deviceTypeObj == null) { - String msg = "Error, device of type: " + deviceType + " does not exist"; + String osVersion = (String) request.getProperty(Constants.OS_VERSION); + Long osVersionValue = DeviceManagerUtil.generateOSVersionValue(osVersion); + if (osVersionValue == null){ + String msg = "Failed to generate OS value, received OS version: " + osVersion + + " is in incorrect format([0-9]+([.][0-9]+)*) or version is invalid."; log.error(msg); - throw new DeviceTypeNotFoundException(msg); + throw new BadRequestException(msg); } + request.setProperty(Constants.OS_VALUE, osVersionValue); try { DeviceManagementDAOFactory.openConnection(); - List devices = deviceDAO.getDevicesExpiredByOSVersion(request, tenantId); + + List devices = deviceDAO.getDevicesExpiredByOSVersion( + request, tenantId); int deviceCount = deviceDAO.getCountOfDeviceExpiredByOSVersion( - deviceType, - (Long) request.getProperty(Constants.OS_BUILD_DATE), - tenantId); + deviceType, osVersionValue, tenantId); paginationResult.setData(devices); paginationResult.setRecordsFiltered(devices.size()); paginationResult.setRecordsTotal(deviceCount); return paginationResult; } catch (SQLException e) { - String msg = "Error occurred while opening a connection to the data source"; + String msg = "Error occurred while opening a connection to the data source."; log.error(msg, e); throw new ReportManagementException(msg, e); } finally { @@ -204,12 +216,12 @@ public class ReportManagementServiceImpl implements ReportManagementService { } } catch (DeviceManagementDAOException e) { - String msg = "Error occurred while retrieving expired devices by a OS build date " + - "for the tenant"; + String msg = "Error occurred while retrieving expired devices by a OS version " + + "for the tenant."; log.error(msg, e); throw new ReportManagementException(msg, e); } catch (DeviceManagementException e) { - String msg = "Error occurred while validating the request"; + String msg = "Error occurred while validating the request."; log.error(msg, e); throw new ReportManagementException(msg, e); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/util/DeviceManagerUtil.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/util/DeviceManagerUtil.java index 1890d399cd9..ff1cd594d42 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/util/DeviceManagerUtil.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/util/DeviceManagerUtil.java @@ -60,6 +60,7 @@ import org.wso2.carbon.device.mgt.core.dao.util.DeviceManagementDAOUtil; import org.wso2.carbon.device.mgt.core.dto.DeviceType; import org.wso2.carbon.device.mgt.core.internal.DeviceManagementDataHolder; import org.wso2.carbon.device.mgt.core.operation.mgt.util.DeviceIDHolder; +import org.wso2.carbon.device.mgt.core.report.mgt.Constants; import org.wso2.carbon.identity.jwt.client.extension.JWTClient; import org.wso2.carbon.identity.jwt.client.extension.dto.AccessTokenInfo; import org.wso2.carbon.identity.jwt.client.extension.exception.JWTClientException; @@ -89,7 +90,11 @@ import java.util.HashMap; import java.util.Hashtable; import java.util.List; import java.util.Map; +import java.util.StringJoiner; import java.util.concurrent.TimeUnit; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.IntStream; public final class DeviceManagerUtil { @@ -694,4 +699,86 @@ public final class DeviceManagerUtil { JWTClient jwtClient = jwtClientManagerService.getJWTClient(); return jwtClient.getAccessToken(clientId, clientSecret, deviceOwner, scopes); } + + /** + *

Generate a value for the passed os version

+ * + *

Value is generated by isolating each position of OS version then adding Zeros up until + * Minor version and Revision have a constant number of digits. + * Eg: 5.1.1 will be 50000100001, 9 will be 90000000000 + *

+ * + *

Above conversion is done in order to fail proof in situations where 6.0.0 can be + * smaller than 5.12.1. + * Eg: 5.12.1 will be 5121 and 6.0.0 will be 600 and 5121 > 600(this statement is incorrect) + *

+ * + * @param osVersion os version(eg: 5.1.1) + * @return {@link Long} generated value + */ + public static Long generateOSVersionValue(String osVersion) { + Matcher osMatcher = Pattern.compile("[0-9]+([.][0-9]+)*").matcher(osVersion); + if (!osMatcher.find()) { + if (log.isDebugEnabled()) { + log.debug("Unable to read OS version. OS version: " + osVersion + "is invalid. " + + "Please follow the following convention [0-9]+([.][0-9]+)*"); + } + return null; + } + osVersion = osMatcher.group(); + + String[] osVersions = osVersion.split("[.]"); + int osVersionsLength = osVersions.length; + + /* + *

Following loop will work for the value generation

+ *

+ {@code Constants.NUM_OF_OS_VERSION_POSITIONS - (i + 1)} was done in-order to identify + which position of the OS version is been used for generation process, so correct number + of Zeros can be generated. + *

+ * + *

+ {@code Constants.NUM_OF_OS_VERSION_DIGITS} this multiplication will make sure that the + values generated will reduce in following order main OS version, minor OS version, Revision. + *

+ */ + return IntStream + .range(0, osVersionsLength) + .mapToLong(i -> (long) (Math.pow(10, (Constants.NUM_OF_OS_VERSION_POSITIONS - (i + 1)) + * Constants.NUM_OF_OS_VERSION_DIGITS) + * Integer.parseInt(osVersions[i]))).sum(); + } + + /** + * Revert a generated value back to a OS version + * + * @param osVersionValue value that should be reverted + * @return {@link String} OS version + */ + /* Following method is unused but was still included in case a requirement occurs to revert the + * generated values in DM_DEVICE_INFO back to a OS versions */ + public static String reverseOSVersionValue(Long osVersionValue) { + StringJoiner joiner = new StringJoiner("."); + + /* + *

Following loop will break the generated value into parts and will recreate the OS version

+ *

+ {@code 10, (i - 1) * Constants.NUM_OF_OS_VERSION_DIGITS} this will break the generated value + creating each OS version position in following order main OS version, minor OS version, + Revision. + *

+ * + */ + for (int i = Constants.NUM_OF_OS_VERSION_POSITIONS; i > 0; i--) { + long osVersion = Double.valueOf( + osVersionValue / Math.pow(10, (i - 1) * Constants.NUM_OF_OS_VERSION_DIGITS)) + .longValue(); + osVersionValue = Double.valueOf( + osVersionValue % Math.pow(10, (i - 1) * Constants.NUM_OF_OS_VERSION_DIGITS)) + .longValue(); + joiner.add(String.valueOf(osVersion)); + } + return joiner.toString(); + } } From 2fab3029ffc05a997ef2d0e9e2d4284e8b4ddad7 Mon Sep 17 00:00:00 2001 From: Yohan Avishke Date: Wed, 4 Mar 2020 13:54:54 +0530 Subject: [PATCH 2/2] Add equation explaining text to the comments and fix fomratting issues Text will explain equation step by step by using. Added missing comments, formatted code lines, formatted license and added more comments. --- .../exceptions/BadRequestException.java | 3 +- .../report/mgt/ReportManagementService.java | 1 + .../dao/impl/device/GenericDeviceDAOImpl.java | 9 ++++-- .../dao/impl/device/OracleDeviceDAOImpl.java | 5 ++-- .../impl/device/PostgreSQLDeviceDAOImpl.java | 5 ++-- .../impl/device/SQLServerDeviceDAOImpl.java | 5 ++-- .../device/mgt/core/report/mgt/Constants.java | 4 +-- .../mgt/core/util/DeviceManagerUtil.java | 29 +++++++++++++++++-- 8 files changed, 41 insertions(+), 20 deletions(-) diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/exceptions/BadRequestException.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/exceptions/BadRequestException.java index 5b1b26e92e9..b7d99da0e09 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/exceptions/BadRequestException.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/exceptions/BadRequestException.java @@ -1,5 +1,4 @@ /* - * * Copyright (c) 2020, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved. * * Entgra (pvt) Ltd. licenses this file to you under the Apache License, @@ -42,5 +41,5 @@ public class BadRequestException extends Exception { public BadRequestException(String message, Throwable cause) { super(message, cause); } - } + diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/report/mgt/ReportManagementService.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/report/mgt/ReportManagementService.java index 6216c3afb25..ef5806d798d 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/report/mgt/ReportManagementService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/report/mgt/ReportManagementService.java @@ -57,6 +57,7 @@ public interface ReportManagementService { * @param request {@link PaginationRequest} * @return {@link PaginationResult} * @throws ReportManagementException Might occur during the business logic or building database query + * @throws BadRequestException Might occur if the given os version or the device type doesn't match */ PaginationResult getDevicesExpiredByOSVersion(PaginationRequest request) throws ReportManagementException, BadRequestException; diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/GenericDeviceDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/GenericDeviceDAOImpl.java index 01de7ca32b0..e2a35770c2b 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/GenericDeviceDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/GenericDeviceDAOImpl.java @@ -867,6 +867,8 @@ public class GenericDeviceDAOImpl extends AbstractDeviceDAOImpl { try { Long osValue = (Long) request.getProperty(Constants.OS_VALUE); Connection conn = getConnection(); + /* following variable is used to identify the datasource type.This is due to a + convert function performed in the query which will depend on the datasource */ String dataSourceType = conn.getMetaData().getDatabaseProductName(); String sql="SELECT " + "d1.DEVICE_TYPE, " + @@ -938,6 +940,8 @@ public class GenericDeviceDAOImpl extends AbstractDeviceDAOImpl { throws DeviceManagementDAOException { try { Connection conn = getConnection(); + /* following variable is used to identify the datasource type.This is due to a + convert function performed in the query which will depend on the datasource */ String dataSourceType = conn.getMetaData().getDatabaseProductName(); String sql = "SELECT " + "COUNT(ddi.DEVICE_ID) AS DEVICE_COUNT " + @@ -964,11 +968,10 @@ public class GenericDeviceDAOImpl extends AbstractDeviceDAOImpl { ps.setLong(4, osValue); try (ResultSet rs = ps.executeQuery()) { - int deviceCount = 0; if (rs.next()) { - deviceCount = rs.getInt("DEVICE_COUNT"); + return rs.getInt("DEVICE_COUNT"); } - return deviceCount; + return 0; } } } catch (SQLException e) { diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/OracleDeviceDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/OracleDeviceDAOImpl.java index 695f1b9ce87..2ef6697453c 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/OracleDeviceDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/OracleDeviceDAOImpl.java @@ -925,11 +925,10 @@ public class OracleDeviceDAOImpl extends AbstractDeviceDAOImpl { ps.setLong(4, osValue); try (ResultSet rs = ps.executeQuery()) { - int deviceCount = 0; if (rs.next()) { - deviceCount = rs.getInt("DEVICE_COUNT"); + return rs.getInt("DEVICE_COUNT"); } - return deviceCount; + return 0; } } } catch (SQLException e) { diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/PostgreSQLDeviceDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/PostgreSQLDeviceDAOImpl.java index 8275c7691fd..fc137897bbe 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/PostgreSQLDeviceDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/PostgreSQLDeviceDAOImpl.java @@ -909,11 +909,10 @@ public class PostgreSQLDeviceDAOImpl extends AbstractDeviceDAOImpl { ps.setLong(4, osValue); try (ResultSet rs = ps.executeQuery()) { - int deviceCount = 0; if (rs.next()) { - deviceCount = rs.getInt("DEVICE_COUNT"); + return rs.getInt("DEVICE_COUNT"); } - return deviceCount; + return 0; } } } catch (SQLException e) { diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/SQLServerDeviceDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/SQLServerDeviceDAOImpl.java index 657e8d7a5c3..ecda3ef66d7 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/SQLServerDeviceDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/SQLServerDeviceDAOImpl.java @@ -725,11 +725,10 @@ public class SQLServerDeviceDAOImpl extends AbstractDeviceDAOImpl { ps.setLong(4, osValue); try (ResultSet rs = ps.executeQuery()) { - int deviceCount = 0; if (rs.next()) { - deviceCount = rs.getInt("DEVICE_COUNT"); + return rs.getInt("DEVICE_COUNT"); } - return deviceCount; + return 0; } } } catch (SQLException e) { diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/report/mgt/Constants.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/report/mgt/Constants.java index 4f5406e5605..2be36d0acfc 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/report/mgt/Constants.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/report/mgt/Constants.java @@ -1,5 +1,4 @@ /* - * * Copyright (c) 2020, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved. * * Entgra (pvt) Ltd. licenses this file to you under the Apache License, @@ -15,10 +14,8 @@ * 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.core.report.mgt; public class Constants { @@ -33,3 +30,4 @@ public class Constants { public static final int NUM_OF_OS_VERSION_DIGITS= 5; public static final int NUM_OF_OS_VERSION_POSITIONS = 3; } + diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/util/DeviceManagerUtil.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/util/DeviceManagerUtil.java index ff1cd594d42..0c0308d6b1a 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/util/DeviceManagerUtil.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/util/DeviceManagerUtil.java @@ -731,7 +731,18 @@ public final class DeviceManagerUtil { int osVersionsLength = osVersions.length; /* - *

Following loop will work for the value generation

+ *

Equation explanation

+ * + *

+ Eg: {@code osVersion == "5.1.1"} will generate an array of {@code ["5","1","1"]} + Following loop for the above result can be broken down as below + * Iteration 1 : {@code Math.pow} result = 5 00000 00000, {@code sum} = 5 00000 00000 + * Iteration 2 : {@code Math.pow} result = 1 00000, {@code sum} = 5 00001 00000 + * Iteration 3 : {@code Math.pow} result = 1, {@code sum} = 5 00001 00001 + To generate the above results I have multiplied the array values with powers of 10. + The constraints used to generate the power of 10 is explained below, + *

+ * *

{@code Constants.NUM_OF_OS_VERSION_POSITIONS - (i + 1)} was done in-order to identify which position of the OS version is been used for generation process, so correct number @@ -742,7 +753,7 @@ public final class DeviceManagerUtil { {@code Constants.NUM_OF_OS_VERSION_DIGITS} this multiplication will make sure that the values generated will reduce in following order main OS version, minor OS version, Revision. *

- */ + */ return IntStream .range(0, osVersionsLength) .mapToLong(i -> (long) (Math.pow(10, (Constants.NUM_OF_OS_VERSION_POSITIONS - (i + 1)) @@ -762,7 +773,19 @@ public final class DeviceManagerUtil { StringJoiner joiner = new StringJoiner("."); /* - *

Following loop will break the generated value into parts and will recreate the OS version

+ *

Equation explanation

+ * + *

+ Eg: {@code osVersionValue == "5 00001 00001"} + Following loop will divide to break down the above number to regenerate the os version + * Iteration 1 : {@code osVersion} = 5 , {@code osVersionValue} = 00001 00001 + * Iteration 2 : {@code osVersion} = 1 , {@code osVersionValue} = 00001 + * Iteration 3 : {@code osVersion} = 1 , {@code osVersionValue} = 0 + Final array = {@code ["5","1","1"]} + To generate the above results I have divided the generated value with powers of 10. + The constraints used to generate the power of 10 is explained below, + *

+ * *

{@code 10, (i - 1) * Constants.NUM_OF_OS_VERSION_DIGITS} this will break the generated value creating each OS version position in following order main OS version, minor OS version,