From 3b7544770d352b38977fa42726b90490a653203e Mon Sep 17 00:00:00 2001 From: Amalka Subasinghe Date: Fri, 21 Apr 2023 22:31:45 +0530 Subject: [PATCH 1/4] avoid replacing _ in device types --- .../mgt/jaxrs/service/impl/DeviceManagementServiceImpl.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) 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 46a37b9f59c..cd657fb5749 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 @@ -826,8 +826,7 @@ public class DeviceManagementServiceImpl implements DeviceManagementService { deviceConfig.setClientId(dcrResponse.getClientId()); deviceConfig.setClientSecret(dcrResponse.getClientSecret()); - StringBuilder scopes = new StringBuilder("device_" + type.replace(" ", "") - .replace("_", "") + "_" + id); + StringBuilder scopes = new StringBuilder("device_" + type.replace(" ", "") + "_" + id); for (String topic : mqttEventTopicStructure) { if (topic.contains("${deviceId}")) { topic = topic.replace("${deviceId}", id); From 290dcf61aec4681a8d47298af1cf3f9a21f95361 Mon Sep 17 00:00:00 2001 From: Amalka Subasinghe Date: Fri, 21 Apr 2023 22:36:45 +0530 Subject: [PATCH 2/4] change format of device scope --- .../mgt/jaxrs/service/impl/DeviceManagementServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 cd657fb5749..f90c45e1066 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 @@ -826,7 +826,7 @@ public class DeviceManagementServiceImpl implements DeviceManagementService { deviceConfig.setClientId(dcrResponse.getClientId()); deviceConfig.setClientSecret(dcrResponse.getClientSecret()); - StringBuilder scopes = new StringBuilder("device_" + type.replace(" ", "") + "_" + id); + StringBuilder scopes = new StringBuilder("device:" + type.replace(" ", "") + ":" + id); for (String topic : mqttEventTopicStructure) { if (topic.contains("${deviceId}")) { topic = topic.replace("${deviceId}", id); From 27cceecd33a2f28f726f3d8e39a88e5cc078ef34 Mon Sep 17 00:00:00 2001 From: Kavin Prathaban Date: Tue, 25 Apr 2023 07:50:37 +0000 Subject: [PATCH 3/4] Fix device enrolment using MSSQL as database (#72) ## Purpose * Fixes https://roadmap.entgra.net/issues/9859 ## Description * Fix device enrolment using MSSQL as database * Fix test case failures of database engine getting a null value Co-authored-by: prathabanKavin Co-authored-by: Pahansith Gunathilake Reviewed-on: https://repository.entgra.net/community/device-mgt-core/pulls/72 Co-authored-by: Kavin Prathaban Co-committed-by: Kavin Prathaban --- .../core/dao/DeviceManagementDAOFactory.java | 18 +- ...pl.java => AbstractEnrollmentDAOImpl.java} | 2 +- .../enrolment/GenericEnrollmentDAOImpl.java | 555 ++++++++++++++++++ .../enrolment/SQLServerEnrollmentDAOImpl.java | 554 +++++++++++++++++ .../dao/DeviceStatusPersistenceTests.java | 14 +- .../core/dao/EnrolmentPersistenceTests.java | 15 +- .../main/resources/dbscripts/cdm/mssql.sql | 16 + 7 files changed, 1157 insertions(+), 17 deletions(-) rename components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/{EnrollmentDAOImpl.java => AbstractEnrollmentDAOImpl.java} (99%) create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/enrolment/GenericEnrollmentDAOImpl.java create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/enrolment/SQLServerEnrollmentDAOImpl.java diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceManagementDAOFactory.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceManagementDAOFactory.java index cbd7c697f4a..b6aadb113f6 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceManagementDAOFactory.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceManagementDAOFactory.java @@ -31,6 +31,8 @@ import org.wso2.carbon.device.mgt.core.dao.impl.device.GenericDeviceDAOImpl; import org.wso2.carbon.device.mgt.core.dao.impl.device.OracleDeviceDAOImpl; import org.wso2.carbon.device.mgt.core.dao.impl.device.PostgreSQLDeviceDAOImpl; import org.wso2.carbon.device.mgt.core.dao.impl.device.SQLServerDeviceDAOImpl; +import org.wso2.carbon.device.mgt.core.dao.impl.enrolment.GenericEnrollmentDAOImpl; +import org.wso2.carbon.device.mgt.core.dao.impl.enrolment.SQLServerEnrollmentDAOImpl; import org.wso2.carbon.device.mgt.core.dao.impl.tracker.TrackerDAOImpl; import org.wso2.carbon.device.mgt.core.dao.util.DeviceManagementDAOUtil; import org.wso2.carbon.device.mgt.core.device.details.mgt.dao.DeviceDetailsDAO; @@ -41,7 +43,6 @@ import org.wso2.carbon.device.mgt.core.privacy.dao.impl.PrivacyComplianceDAOImpl import javax.sql.DataSource; import java.sql.Connection; import java.sql.SQLException; -import java.sql.Timestamp; import java.util.Hashtable; import java.util.List; @@ -122,7 +123,20 @@ public class DeviceManagementDAOFactory { } public static EnrollmentDAO getEnrollmentDAO() { - return new EnrollmentDAOImpl(); + if (databaseEngine != null) { + switch (databaseEngine) { + case DeviceManagementConstants.DataBaseTypes.DB_TYPE_MSSQL: + return new SQLServerEnrollmentDAOImpl(); + case DeviceManagementConstants.DataBaseTypes.DB_TYPE_POSTGRESQL: + case DeviceManagementConstants.DataBaseTypes.DB_TYPE_ORACLE: + case DeviceManagementConstants.DataBaseTypes.DB_TYPE_H2: + case DeviceManagementConstants.DataBaseTypes.DB_TYPE_MYSQL: + return new GenericEnrollmentDAOImpl(); + default: + throw new UnsupportedDatabaseEngineException("Unsupported database engine : " + databaseEngine); + } + } + throw new IllegalStateException("Database engine has not initialized properly."); } public static TrackerDAO getTrackerDAO() { diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/EnrollmentDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractEnrollmentDAOImpl.java similarity index 99% rename from components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/EnrollmentDAOImpl.java rename to components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractEnrollmentDAOImpl.java index 7b3e08cd509..a3757bc523d 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/EnrollmentDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractEnrollmentDAOImpl.java @@ -37,7 +37,7 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; -public class EnrollmentDAOImpl implements EnrollmentDAO { +public abstract class AbstractEnrollmentDAOImpl implements EnrollmentDAO { @Override public EnrolmentInfo addEnrollment(int deviceId, EnrolmentInfo enrolmentInfo, diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/enrolment/GenericEnrollmentDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/enrolment/GenericEnrollmentDAOImpl.java new file mode 100644 index 00000000000..041efbf285d --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/enrolment/GenericEnrollmentDAOImpl.java @@ -0,0 +1,555 @@ +/* + * Copyright (c) 2023, 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 + * + * 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.core.dao.impl.enrolment; + +import org.wso2.carbon.context.PrivilegedCarbonContext; +import org.wso2.carbon.device.mgt.common.Device; +import org.wso2.carbon.device.mgt.common.DeviceManagementConstants; +import org.wso2.carbon.device.mgt.common.EnrolmentInfo; +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.AbstractEnrollmentDAOImpl; +import org.wso2.carbon.device.mgt.core.dao.util.DeviceManagementDAOUtil; + +import java.sql.*; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +public class GenericEnrollmentDAOImpl extends AbstractEnrollmentDAOImpl { + + @Override + public EnrolmentInfo addEnrollment(int deviceId, EnrolmentInfo enrolmentInfo, + int tenantId) throws DeviceManagementDAOException { + Connection conn; + PreparedStatement stmt = null; + ResultSet rs = null; + try { + conn = this.getConnection(); + String sql = "INSERT INTO DM_ENROLMENT(DEVICE_ID, OWNER, OWNERSHIP, STATUS, " + + "DATE_OF_ENROLMENT, DATE_OF_LAST_UPDATE, TENANT_ID) VALUES(?, ?, ?, ?, ?, ?, ?)"; + stmt = conn.prepareStatement(sql, new String[] {"id"}); + Timestamp enrollmentTime = new Timestamp(new Date().getTime()); + stmt.setInt(1, deviceId); + stmt.setString(2, enrolmentInfo.getOwner()); + stmt.setString(3, enrolmentInfo.getOwnership().toString()); + stmt.setString(4, enrolmentInfo.getStatus().toString()); + stmt.setTimestamp(5, enrollmentTime); + stmt.setTimestamp(6, enrollmentTime); + stmt.setInt(7, tenantId); + stmt.execute(); + + rs = stmt.getGeneratedKeys(); + if (rs.next()) { + int enrolmentId = rs.getInt(1); + enrolmentInfo.setId(enrolmentId); + enrolmentInfo.setDateOfEnrolment(enrollmentTime.getTime()); + enrolmentInfo.setDateOfLastUpdate(enrollmentTime.getTime()); + addDeviceStatus(enrolmentId, enrolmentInfo.getStatus()); + return enrolmentInfo; + } + return null; + } catch (SQLException e) { + e.printStackTrace(); + throw new DeviceManagementDAOException("Error occurred while adding enrolment configuration", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + } + } + + @Override + public int updateEnrollment(EnrolmentInfo enrolmentInfo, int tenantId) throws DeviceManagementDAOException { + Connection conn; + PreparedStatement stmt = null; + ResultSet rs = null; + try { + conn = this.getConnection(); + String sql = "UPDATE DM_ENROLMENT SET OWNERSHIP = ?, STATUS = ?, DATE_OF_LAST_UPDATE = ? " + + "WHERE ID = ? AND TENANT_ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setString(1, enrolmentInfo.getOwnership().toString()); + stmt.setString(2, enrolmentInfo.getStatus().toString()); + stmt.setTimestamp(3, new Timestamp(new Date().getTime())); + stmt.setInt(4, enrolmentInfo.getId()); + stmt.setInt(5, tenantId); + int updatedCount = stmt.executeUpdate(); + if (updatedCount == 1){ + addDeviceStatus(enrolmentInfo.getId(), enrolmentInfo.getStatus()); + } + return updatedCount; + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while updating enrolment configuration", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + } + } + + @Override + public boolean updateEnrollmentStatus(List enrolmentInfos) throws DeviceManagementDAOException { + Connection conn; + PreparedStatement stmt = null; + ResultSet rs = null; + boolean status = false; + int updateStatus = -1; + try { + conn = this.getConnection(); + String sql = "UPDATE DM_ENROLMENT SET STATUS = ? WHERE ID = ?"; + stmt = conn.prepareStatement(sql); + if (conn.getMetaData().supportsBatchUpdates()) { + for (EnrolmentInfo enrolmentInfo : enrolmentInfos) { + stmt.setString(1, enrolmentInfo.getStatus().toString()); + stmt.setInt(2, enrolmentInfo.getId()); + stmt.addBatch(); + } + updateStatus = stmt.executeBatch().length; + } else { + for (EnrolmentInfo enrolmentInfo : enrolmentInfos) { + stmt.setString(1, enrolmentInfo.getStatus().toString()); + stmt.setInt(2, enrolmentInfo.getId()); + updateStatus = stmt.executeUpdate(); + } + } + if (updateStatus > 0) { + status = true; + for (EnrolmentInfo enrolmentInfo : enrolmentInfos) { + addDeviceStatus(enrolmentInfo); + } + } + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while updating enrolment status of given device-list.", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + } + return status; + } + + @Override + public int removeEnrollment(int deviceId, String currentOwner, + int tenantId) throws DeviceManagementDAOException { + Connection conn; + PreparedStatement stmt = null; + ResultSet rs = null; + int status = -1; + try { + conn = this.getConnection(); + String sql = "DELETE FROM DM_ENROLMENT WHERE DEVICE_ID = ? AND OWNER = ? AND TENANT_ID = ?"; + stmt = conn.prepareStatement(sql, new String[] {"id"}); + stmt.setInt(1, deviceId); + stmt.setString(2, currentOwner); + stmt.setInt(3, tenantId); + stmt.executeUpdate(); + + rs = stmt.getGeneratedKeys(); + if (rs.next()) { + status = 1; + } + return status; + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while removing device enrolment", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + } + } + + private int getCountOfDevicesOfOwner(String owner, int tenantID) throws DeviceManagementDAOException { + Connection conn; + PreparedStatement stmt = null; + ResultSet rs = null; + int count = 0; + try { + conn = this.getConnection(); + String checkQuery = "SELECT COUNT(ID) AS COUNT FROM DM_ENROLMENT WHERE OWNER = ? AND TENANT_ID = ?"; + stmt = conn.prepareStatement(checkQuery); + stmt.setString(1, owner); + stmt.setInt(2, tenantID); + rs = stmt.executeQuery(); + if(rs.next()){ + count = rs.getInt("COUNT"); + } + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while trying to get device " + + "count of Owner : "+owner, e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + } + return count; + } + + @Override + public boolean setStatus(String currentOwner, EnrolmentInfo.Status status, + int tenantId) throws DeviceManagementDAOException { + return setStatusAllDevices(currentOwner, status, tenantId); + } + + @Override + public boolean setStatusAllDevices(String currentOwner, EnrolmentInfo.Status status, int tenantId) + throws DeviceManagementDAOException{ + Connection conn; + PreparedStatement stmt = null; + Timestamp updateTime = new Timestamp(new Date().getTime()); + if(getCountOfDevicesOfOwner(currentOwner, tenantId) > 0){ + try { + conn = this.getConnection(); + String sql = "UPDATE DM_ENROLMENT SET STATUS = ?, DATE_OF_LAST_UPDATE = ? WHERE OWNER = ? AND TENANT_ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setString(1, status.toString()); + stmt.setTimestamp(2, updateTime); + stmt.setString(3, currentOwner); + stmt.setInt(4, tenantId); + stmt.executeUpdate(); + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while setting the status of device enrolment", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, null); + } + return addDeviceStatus(currentOwner, status, tenantId); + } else { + return false; + } + } + + @Override + public boolean setStatus(int enrolmentID, EnrolmentInfo.Status status, int tenantId) throws DeviceManagementDAOException { + Connection conn; + PreparedStatement stmt = null; + Timestamp updateTime = new Timestamp(new Date().getTime()); + try { + conn = this.getConnection(); + String sql = "UPDATE DM_ENROLMENT SET STATUS = ?, DATE_OF_LAST_UPDATE = ? WHERE ID = ? AND TENANT_ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setString(1, status.toString()); + stmt.setTimestamp(2, updateTime); + stmt.setInt(3, enrolmentID); + stmt.setInt(4, tenantId); + int updatedRowCount = stmt.executeUpdate(); + if (updatedRowCount != 1){ + throw new DeviceManagementDAOException("Error occurred while setting the status of device enrolment: "+ + updatedRowCount + " rows were updated instead of one row!!!"); + } + // save the device status history + addDeviceStatus(enrolmentID, status); + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while setting the status of device enrolment", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, null); + } + return true; + } + + private boolean addDeviceStatus(EnrolmentInfo config) throws DeviceManagementDAOException { + return addDeviceStatus(config.getId(), config.getStatus()); + } + + private boolean addDeviceStatus(String currentOwner, EnrolmentInfo.Status status, int tenantId) throws DeviceManagementDAOException { + Connection conn; + String changedBy = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername(); + if (changedBy == null){ + changedBy = DeviceManagementConstants.MaintenanceProperties.MAINTENANCE_USER; + } + PreparedStatement stmt = null; + ResultSet rs = null; + List enrolmentInfoList = new ArrayList<>(); + try { + conn = this.getConnection(); + String sql = "SELECT ID, DEVICE_ID, OWNER, OWNERSHIP, STATUS, IS_TRANSFERRED, DATE_OF_ENROLMENT, " + + "DATE_OF_LAST_UPDATE, TENANT_ID FROM DM_ENROLMENT WHERE OWNER = ? AND TENANT_ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setString(1, currentOwner); + stmt.setInt(2, tenantId); + rs = stmt.executeQuery(); + while (rs.next()) { + int enrolmentId = rs.getInt("ID"); + int deviceId = rs.getInt("DEVICE_ID"); + enrolmentInfoList.add(new int[]{enrolmentId, deviceId}); + } + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + Timestamp updateTime = new Timestamp(new Date().getTime()); + sql = "INSERT INTO DM_DEVICE_STATUS (ENROLMENT_ID, DEVICE_ID, STATUS, UPDATE_TIME, CHANGED_BY) VALUES(?, ?, ?, ?, ?)"; + try (PreparedStatement ps = conn.prepareStatement(sql)) { + if (conn.getMetaData().supportsBatchUpdates()) { + for(int[] info: enrolmentInfoList){ + ps.setInt(1, info[0]); + ps.setInt(2, info[1]); + ps.setString(3, status.toString()); + ps.setTimestamp(4, updateTime); + ps.setString(5, changedBy); + ps.addBatch(); + } + int[] batchResult = ps.executeBatch(); + for (int i : batchResult) { + if (i == 0 || i == Statement.SUCCESS_NO_INFO || i == Statement.EXECUTE_FAILED) { + return false; + } + } + } else { + for(int[] info: enrolmentInfoList){ + ps.setInt(1, info[0]); + ps.setInt(2, info[1]); + ps.setString(3, status.toString()); + ps.setTimestamp(4, updateTime); + ps.setString(5, changedBy); + ps.execute(); + } + + } + } + + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while retrieving the enrolments " + + "information of owner '" + currentOwner + "'", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + } + return true; + } + + private boolean addDeviceStatus(int enrolmentId, EnrolmentInfo.Status status) throws DeviceManagementDAOException { + Connection conn; + String changedBy = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername(); + if (changedBy == null){ + changedBy = DeviceManagementConstants.MaintenanceProperties.MAINTENANCE_USER; + } + PreparedStatement stmt = null; + try { + conn = this.getConnection(); + // get the device id and last udpated status from the device status table + String sql = "SELECT DEVICE_ID, STATUS FROM DM_DEVICE_STATUS WHERE ENROLMENT_ID = ? ORDER BY UPDATE_TIME DESC LIMIT 1"; + stmt = conn.prepareStatement(sql); + stmt.setInt(1, enrolmentId); + ResultSet rs = stmt.executeQuery(); + int deviceId = -1; + EnrolmentInfo.Status previousStatus = null; + if (rs.next()) { + // if there is a record corresponding to the enrolment we save the status and the device id + previousStatus = EnrolmentInfo.Status.valueOf(rs.getString("STATUS")); + deviceId = rs.getInt("DEVICE_ID"); + } + DeviceManagementDAOUtil.cleanupResources(stmt, null); + // if there was no record for the enrolment or the previous status is not the same as the current status + // we'll add a record + if (previousStatus == null || previousStatus != status){ + if (deviceId == -1) { + // we need the device id in order to add a new record, therefore we get it from the enrolment table + sql = "SELECT DEVICE_ID FROM DM_ENROLMENT WHERE ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setInt(1, enrolmentId); + rs = stmt.executeQuery(); + if (rs.next()) { + deviceId = rs.getInt("DEVICE_ID"); + } else { + // if there were no records corresponding to the enrolment id this is a problem. i.e. enrolment + // id is invalid + throw new DeviceManagementDAOException("Error occurred while setting the status of device enrolment: no record for enrolment id " + enrolmentId); + } + DeviceManagementDAOUtil.cleanupResources(stmt, null); + } + + sql = "INSERT INTO DM_DEVICE_STATUS (ENROLMENT_ID, DEVICE_ID, STATUS, UPDATE_TIME, CHANGED_BY) VALUES(?, ?, ?, ?, ?)"; + stmt = conn.prepareStatement(sql); + Timestamp updateTime = new Timestamp(new Date().getTime()); + stmt.setInt(1, enrolmentId); + stmt.setInt(2, deviceId); + stmt.setString(3, status.toString()); + stmt.setTimestamp(4, updateTime); + stmt.setString(5, changedBy); + stmt.execute(); + } else { + // no need to update status since the last recorded status is the same as the current status + } + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while setting the status of device", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, null); + } + return true; + } + @Override + public EnrolmentInfo.Status getStatus(int deviceId, String currentOwner, + int tenantId) throws DeviceManagementDAOException { + Connection conn; + PreparedStatement stmt = null; + ResultSet rs = null; + EnrolmentInfo.Status status = null; + try { + conn = this.getConnection(); + String sql = "SELECT STATUS FROM DM_ENROLMENT WHERE DEVICE_ID = ? AND OWNER = ? AND TENANT_ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setInt(1, deviceId); + stmt.setString(2, currentOwner); + stmt.setInt(3, tenantId); + rs = stmt.executeQuery(); + if (rs.next()) { + status = EnrolmentInfo.Status.valueOf(rs.getString("STATUS")); + } + return status; + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while setting the status of device enrolment", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + } + } + + @Override + public EnrolmentInfo getEnrollment(int deviceId, String currentOwner, + int tenantId) throws DeviceManagementDAOException { + Connection conn; + PreparedStatement stmt = null; + ResultSet rs = null; + EnrolmentInfo enrolmentInfo = null; + try { + conn = this.getConnection(); + String sql = "SELECT ID, DEVICE_ID, OWNER, OWNERSHIP, STATUS, IS_TRANSFERRED, DATE_OF_ENROLMENT, " + + "DATE_OF_LAST_UPDATE, TENANT_ID FROM DM_ENROLMENT WHERE DEVICE_ID = ? AND OWNER = ? AND TENANT_ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setInt(1, deviceId); + stmt.setString(2, currentOwner); + stmt.setInt(3, tenantId); + rs = stmt.executeQuery(); + if (rs.next()) { + enrolmentInfo = this.loadEnrolment(rs); + } + return enrolmentInfo; + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while retrieving the enrolment " + + "information of user '" + currentOwner + "' upon device '" + deviceId + "'", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + } + } + + @Override + public EnrolmentInfo getEnrollment(int deviceId, int tenantId) throws DeviceManagementDAOException { + Connection conn; + PreparedStatement stmt = null; + ResultSet rs = null; + EnrolmentInfo enrolmentInfo = null; + try { + conn = this.getConnection(); + String sql = "SELECT ID, DEVICE_ID, OWNER, OWNERSHIP, STATUS, IS_TRANSFERRED, DATE_OF_ENROLMENT, " + + "DATE_OF_LAST_UPDATE, TENANT_ID FROM DM_ENROLMENT WHERE DEVICE_ID = ? AND TENANT_ID = ? " + + "ORDER BY DATE_OF_LAST_UPDATE DESC"; + stmt = conn.prepareStatement(sql); + stmt.setInt(1, deviceId); + stmt.setInt(2, tenantId); + rs = stmt.executeQuery(); + if (rs.next()) { + enrolmentInfo = this.loadEnrolment(rs); + } + return enrolmentInfo; + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while retrieving the enrolment " + + "information of device '" + deviceId + "'", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + } + } + + @Override + public List getEnrollmentsOfUser(int deviceId, String user, int tenantId) + throws DeviceManagementDAOException { + List enrolmentInfos = new ArrayList<>(); + Connection conn; + PreparedStatement stmt = null; + ResultSet rs = null; + EnrolmentInfo enrolmentInfo = null; + try { + conn = this.getConnection(); + String sql = "SELECT ID, DEVICE_ID, OWNER, OWNERSHIP, STATUS, IS_TRANSFERRED, DATE_OF_ENROLMENT, " + + "DATE_OF_LAST_UPDATE, TENANT_ID FROM DM_ENROLMENT WHERE DEVICE_ID = ? AND OWNER = ? AND TENANT_ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setInt(1, deviceId); + stmt.setString(2, user); + stmt.setInt(3, tenantId); + rs = stmt.executeQuery(); + while (rs.next()) { + enrolmentInfo = this.loadEnrolment(rs); + enrolmentInfos.add(enrolmentInfo); + } + return enrolmentInfos; + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while retrieving the enrolments " + + "information of user '" + user + "' upon device '" + deviceId + "'", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + } + } + + @Override + public boolean updateOwnerOfEnrollment(List devices, String owner, int tenantId) + throws DeviceManagementDAOException { + try { + Connection conn = this.getConnection(); + boolean updateStatus = true; + String sql = "UPDATE DM_ENROLMENT " + + "SET OWNER = ?, IS_TRANSFERRED = ?, DATE_OF_LAST_UPDATE = ? " + + "WHERE ID = ? AND TENANT_ID = ?"; + try (PreparedStatement ps = conn.prepareStatement(sql)) { + if (conn.getMetaData().supportsBatchUpdates()) { + for (Device device : devices) { + ps.setString(1, owner); + ps.setBoolean(2, device.getEnrolmentInfo().isTransferred()); + ps.setTimestamp(3, new Timestamp(new Date().getTime())); + ps.setInt(4, device.getEnrolmentInfo().getId()); + ps.setInt(5, tenantId); + ps.addBatch(); + } + int[] batchResult = ps.executeBatch(); + for (int i : batchResult) { + if (i == 0 || i == Statement.SUCCESS_NO_INFO || i == Statement.EXECUTE_FAILED) { + updateStatus = false; + break; + } + } + } else { + for (Device device : devices) { + ps.setString(1, owner); + ps.setBoolean(2, device.getEnrolmentInfo().isTransferred()); + ps.setInt(3, device.getId()); + ps.setInt(4, tenantId); + if (ps.executeUpdate() == 0) { + updateStatus = false; + break; + } + } + } + } + return updateStatus; + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while obtaining the DB connection to update the " + + "owner of the device enrollment.", e); + } + } + + private Connection getConnection() throws SQLException { + return DeviceManagementDAOFactory.getConnection(); + } + + private EnrolmentInfo loadEnrolment(ResultSet rs) throws SQLException { + EnrolmentInfo enrolmentInfo = new EnrolmentInfo(); + enrolmentInfo.setOwner(rs.getString("OWNER")); + enrolmentInfo.setOwnership(EnrolmentInfo.OwnerShip.valueOf(rs.getString("OWNERSHIP"))); + enrolmentInfo.setTransferred(rs.getBoolean("IS_TRANSFERRED")); + enrolmentInfo.setDateOfEnrolment(rs.getTimestamp("DATE_OF_ENROLMENT").getTime()); + enrolmentInfo.setDateOfLastUpdate(rs.getTimestamp("DATE_OF_LAST_UPDATE").getTime()); + enrolmentInfo.setStatus(EnrolmentInfo.Status.valueOf(rs.getString("STATUS"))); + enrolmentInfo.setId(rs.getInt("ID")); + return enrolmentInfo; + } + +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/enrolment/SQLServerEnrollmentDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/enrolment/SQLServerEnrollmentDAOImpl.java new file mode 100644 index 00000000000..8041d07a598 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/enrolment/SQLServerEnrollmentDAOImpl.java @@ -0,0 +1,554 @@ +/* + * Copyright (c) 2023, 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 + * + * 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.core.dao.impl.enrolment; + +import org.wso2.carbon.context.PrivilegedCarbonContext; +import org.wso2.carbon.device.mgt.common.Device; +import org.wso2.carbon.device.mgt.common.DeviceManagementConstants; +import org.wso2.carbon.device.mgt.common.EnrolmentInfo; +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.AbstractEnrollmentDAOImpl; +import org.wso2.carbon.device.mgt.core.dao.util.DeviceManagementDAOUtil; +import java.sql.*; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +public class SQLServerEnrollmentDAOImpl extends AbstractEnrollmentDAOImpl { + + @Override + public EnrolmentInfo addEnrollment(int deviceId, EnrolmentInfo enrolmentInfo, + int tenantId) throws DeviceManagementDAOException { + Connection conn; + PreparedStatement stmt = null; + ResultSet rs = null; + try { + conn = this.getConnection(); + String sql = "INSERT INTO DM_ENROLMENT(DEVICE_ID, OWNER, OWNERSHIP, STATUS, " + + "DATE_OF_ENROLMENT, DATE_OF_LAST_UPDATE, TENANT_ID) VALUES(?, ?, ?, ?, ?, ?, ?)"; + stmt = conn.prepareStatement(sql, new String[] {"id"}); + Timestamp enrollmentTime = new Timestamp(new Date().getTime()); + stmt.setInt(1, deviceId); + stmt.setString(2, enrolmentInfo.getOwner()); + stmt.setString(3, enrolmentInfo.getOwnership().toString()); + stmt.setString(4, enrolmentInfo.getStatus().toString()); + stmt.setTimestamp(5, enrollmentTime); + stmt.setTimestamp(6, enrollmentTime); + stmt.setInt(7, tenantId); + stmt.execute(); + + rs = stmt.getGeneratedKeys(); + if (rs.next()) { + int enrolmentId = rs.getInt(1); + enrolmentInfo.setId(enrolmentId); + enrolmentInfo.setDateOfEnrolment(enrollmentTime.getTime()); + enrolmentInfo.setDateOfLastUpdate(enrollmentTime.getTime()); + addDeviceStatus(enrolmentId, enrolmentInfo.getStatus()); + return enrolmentInfo; + } + return null; + } catch (SQLException e) { + e.printStackTrace(); + throw new DeviceManagementDAOException("Error occurred while adding enrolment configuration", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + } + } + + @Override + public int updateEnrollment(EnrolmentInfo enrolmentInfo, int tenantId) throws DeviceManagementDAOException { + Connection conn; + PreparedStatement stmt = null; + ResultSet rs = null; + try { + conn = this.getConnection(); + String sql = "UPDATE DM_ENROLMENT SET OWNERSHIP = ?, STATUS = ?, DATE_OF_LAST_UPDATE = ? " + + "WHERE ID = ? AND TENANT_ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setString(1, enrolmentInfo.getOwnership().toString()); + stmt.setString(2, enrolmentInfo.getStatus().toString()); + stmt.setTimestamp(3, new Timestamp(new Date().getTime())); + stmt.setInt(4, enrolmentInfo.getId()); + stmt.setInt(5, tenantId); + int updatedCount = stmt.executeUpdate(); + if (updatedCount == 1){ + addDeviceStatus(enrolmentInfo.getId(), enrolmentInfo.getStatus()); + } + return updatedCount; + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while updating enrolment configuration", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + } + } + + @Override + public boolean updateEnrollmentStatus(List enrolmentInfos) throws DeviceManagementDAOException { + Connection conn; + PreparedStatement stmt = null; + ResultSet rs = null; + boolean status = false; + int updateStatus = -1; + try { + conn = this.getConnection(); + String sql = "UPDATE DM_ENROLMENT SET STATUS = ? WHERE ID = ?"; + stmt = conn.prepareStatement(sql); + if (conn.getMetaData().supportsBatchUpdates()) { + for (EnrolmentInfo enrolmentInfo : enrolmentInfos) { + stmt.setString(1, enrolmentInfo.getStatus().toString()); + stmt.setInt(2, enrolmentInfo.getId()); + stmt.addBatch(); + } + updateStatus = stmt.executeBatch().length; + } else { + for (EnrolmentInfo enrolmentInfo : enrolmentInfos) { + stmt.setString(1, enrolmentInfo.getStatus().toString()); + stmt.setInt(2, enrolmentInfo.getId()); + updateStatus = stmt.executeUpdate(); + } + } + if (updateStatus > 0) { + status = true; + for (EnrolmentInfo enrolmentInfo : enrolmentInfos) { + addDeviceStatus(enrolmentInfo); + } + } + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while updating enrolment status of given device-list.", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + } + return status; + } + + @Override + public int removeEnrollment(int deviceId, String currentOwner, + int tenantId) throws DeviceManagementDAOException { + Connection conn; + PreparedStatement stmt = null; + ResultSet rs = null; + int status = -1; + try { + conn = this.getConnection(); + String sql = "DELETE FROM DM_ENROLMENT WHERE DEVICE_ID = ? AND OWNER = ? AND TENANT_ID = ?"; + stmt = conn.prepareStatement(sql, new String[] {"id"}); + stmt.setInt(1, deviceId); + stmt.setString(2, currentOwner); + stmt.setInt(3, tenantId); + stmt.executeUpdate(); + + rs = stmt.getGeneratedKeys(); + if (rs.next()) { + status = 1; + } + return status; + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while removing device enrolment", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + } + } + + private int getCountOfDevicesOfOwner(String owner, int tenantID) throws DeviceManagementDAOException { + Connection conn; + PreparedStatement stmt = null; + ResultSet rs = null; + int count = 0; + try { + conn = this.getConnection(); + String checkQuery = "SELECT COUNT(ID) AS COUNT FROM DM_ENROLMENT WHERE OWNER = ? AND TENANT_ID = ?"; + stmt = conn.prepareStatement(checkQuery); + stmt.setString(1, owner); + stmt.setInt(2, tenantID); + rs = stmt.executeQuery(); + if(rs.next()){ + count = rs.getInt("COUNT"); + } + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while trying to get device " + + "count of Owner : "+owner, e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + } + return count; + } + + @Override + public boolean setStatus(String currentOwner, EnrolmentInfo.Status status, + int tenantId) throws DeviceManagementDAOException { + return setStatusAllDevices(currentOwner, status, tenantId); + } + + @Override + public boolean setStatusAllDevices(String currentOwner, EnrolmentInfo.Status status, int tenantId) + throws DeviceManagementDAOException{ + Connection conn; + PreparedStatement stmt = null; + Timestamp updateTime = new Timestamp(new Date().getTime()); + if(getCountOfDevicesOfOwner(currentOwner, tenantId) > 0){ + try { + conn = this.getConnection(); + String sql = "UPDATE DM_ENROLMENT SET STATUS = ?, DATE_OF_LAST_UPDATE = ? WHERE OWNER = ? AND TENANT_ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setString(1, status.toString()); + stmt.setTimestamp(2, updateTime); + stmt.setString(3, currentOwner); + stmt.setInt(4, tenantId); + stmt.executeUpdate(); + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while setting the status of device enrolment", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, null); + } + return addDeviceStatus(currentOwner, status, tenantId); + } else { + return false; + } + } + + @Override + public boolean setStatus(int enrolmentID, EnrolmentInfo.Status status, int tenantId) throws DeviceManagementDAOException { + Connection conn; + PreparedStatement stmt = null; + Timestamp updateTime = new Timestamp(new Date().getTime()); + try { + conn = this.getConnection(); + String sql = "UPDATE DM_ENROLMENT SET STATUS = ?, DATE_OF_LAST_UPDATE = ? WHERE ID = ? AND TENANT_ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setString(1, status.toString()); + stmt.setTimestamp(2, updateTime); + stmt.setInt(3, enrolmentID); + stmt.setInt(4, tenantId); + int updatedRowCount = stmt.executeUpdate(); + if (updatedRowCount != 1){ + throw new DeviceManagementDAOException("Error occurred while setting the status of device enrolment: "+ + updatedRowCount + " rows were updated instead of one row!!!"); + } + // save the device status history + addDeviceStatus(enrolmentID, status); + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while setting the status of device enrolment", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, null); + } + return true; + } + + private boolean addDeviceStatus(EnrolmentInfo config) throws DeviceManagementDAOException { + return addDeviceStatus(config.getId(), config.getStatus()); + } + + private boolean addDeviceStatus(String currentOwner, EnrolmentInfo.Status status, int tenantId) throws DeviceManagementDAOException { + Connection conn; + String changedBy = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername(); + if (changedBy == null){ + changedBy = DeviceManagementConstants.MaintenanceProperties.MAINTENANCE_USER; + } + PreparedStatement stmt = null; + ResultSet rs = null; + List enrolmentInfoList = new ArrayList<>(); + try { + conn = this.getConnection(); + String sql = "SELECT ID, DEVICE_ID, OWNER, OWNERSHIP, STATUS, IS_TRANSFERRED, DATE_OF_ENROLMENT, " + + "DATE_OF_LAST_UPDATE, TENANT_ID FROM DM_ENROLMENT WHERE OWNER = ? AND TENANT_ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setString(1, currentOwner); + stmt.setInt(2, tenantId); + rs = stmt.executeQuery(); + while (rs.next()) { + int enrolmentId = rs.getInt("ID"); + int deviceId = rs.getInt("DEVICE_ID"); + enrolmentInfoList.add(new int[]{enrolmentId, deviceId}); + } + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + Timestamp updateTime = new Timestamp(new Date().getTime()); + sql = "INSERT INTO DM_DEVICE_STATUS (ENROLMENT_ID, DEVICE_ID, STATUS, UPDATE_TIME, CHANGED_BY) VALUES(?, ?, ?, ?, ?)"; + try (PreparedStatement ps = conn.prepareStatement(sql)) { + if (conn.getMetaData().supportsBatchUpdates()) { + for(int[] info: enrolmentInfoList){ + ps.setInt(1, info[0]); + ps.setInt(2, info[1]); + ps.setString(3, status.toString()); + ps.setTimestamp(4, updateTime); + ps.setString(5, changedBy); + ps.addBatch(); + } + int[] batchResult = ps.executeBatch(); + for (int i : batchResult) { + if (i == 0 || i == Statement.SUCCESS_NO_INFO || i == Statement.EXECUTE_FAILED) { + return false; + } + } + } else { + for(int[] info: enrolmentInfoList){ + ps.setInt(1, info[0]); + ps.setInt(2, info[1]); + ps.setString(3, status.toString()); + ps.setTimestamp(4, updateTime); + ps.setString(5, changedBy); + ps.execute(); + } + + } + } + + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while retrieving the enrolments " + + "information of owner '" + currentOwner + "'", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + } + return true; + } + + private boolean addDeviceStatus(int enrolmentId, EnrolmentInfo.Status status) throws DeviceManagementDAOException { + Connection conn; + String changedBy = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername(); + if (changedBy == null){ + changedBy = DeviceManagementConstants.MaintenanceProperties.MAINTENANCE_USER; + } + PreparedStatement stmt = null; + try { + conn = this.getConnection(); + // get the device id and last udpated status from the device status table + String sql = "SELECT TOP 1 DEVICE_ID, STATUS FROM DM_DEVICE_STATUS WHERE ENROLMENT_ID = ? ORDER BY UPDATE_TIME DESC"; + stmt = conn.prepareStatement(sql); + stmt.setInt(1, enrolmentId); + ResultSet rs = stmt.executeQuery(); + int deviceId = -1; + EnrolmentInfo.Status previousStatus = null; + if (rs.next()) { + // if there is a record corresponding to the enrolment we save the status and the device id + previousStatus = EnrolmentInfo.Status.valueOf(rs.getString("STATUS")); + deviceId = rs.getInt("DEVICE_ID"); + } + DeviceManagementDAOUtil.cleanupResources(stmt, null); + // if there was no record for the enrolment or the previous status is not the same as the current status + // we'll add a record + if (previousStatus == null || previousStatus != status){ + if (deviceId == -1) { + // we need the device id in order to add a new record, therefore we get it from the enrolment table + sql = "SELECT DEVICE_ID FROM DM_ENROLMENT WHERE ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setInt(1, enrolmentId); + rs = stmt.executeQuery(); + if (rs.next()) { + deviceId = rs.getInt("DEVICE_ID"); + } else { + // if there were no records corresponding to the enrolment id this is a problem. i.e. enrolment + // id is invalid + throw new DeviceManagementDAOException("Error occurred while setting the status of device enrolment: no record for enrolment id " + enrolmentId); + } + DeviceManagementDAOUtil.cleanupResources(stmt, null); + } + + sql = "INSERT INTO DM_DEVICE_STATUS (ENROLMENT_ID, DEVICE_ID, STATUS, UPDATE_TIME, CHANGED_BY) VALUES(?, ?, ?, ?, ?)"; + stmt = conn.prepareStatement(sql); + Timestamp updateTime = new Timestamp(new Date().getTime()); + stmt.setInt(1, enrolmentId); + stmt.setInt(2, deviceId); + stmt.setString(3, status.toString()); + stmt.setTimestamp(4, updateTime); + stmt.setString(5, changedBy); + stmt.execute(); + } else { + // no need to update status since the last recorded status is the same as the current status + } + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while setting the status of device", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, null); + } + return true; + } + @Override + public EnrolmentInfo.Status getStatus(int deviceId, String currentOwner, + int tenantId) throws DeviceManagementDAOException { + Connection conn; + PreparedStatement stmt = null; + ResultSet rs = null; + EnrolmentInfo.Status status = null; + try { + conn = this.getConnection(); + String sql = "SELECT STATUS FROM DM_ENROLMENT WHERE DEVICE_ID = ? AND OWNER = ? AND TENANT_ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setInt(1, deviceId); + stmt.setString(2, currentOwner); + stmt.setInt(3, tenantId); + rs = stmt.executeQuery(); + if (rs.next()) { + status = EnrolmentInfo.Status.valueOf(rs.getString("STATUS")); + } + return status; + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while setting the status of device enrolment", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + } + } + + @Override + public EnrolmentInfo getEnrollment(int deviceId, String currentOwner, + int tenantId) throws DeviceManagementDAOException { + Connection conn; + PreparedStatement stmt = null; + ResultSet rs = null; + EnrolmentInfo enrolmentInfo = null; + try { + conn = this.getConnection(); + String sql = "SELECT ID, DEVICE_ID, OWNER, OWNERSHIP, STATUS, IS_TRANSFERRED, DATE_OF_ENROLMENT, " + + "DATE_OF_LAST_UPDATE, TENANT_ID FROM DM_ENROLMENT WHERE DEVICE_ID = ? AND OWNER = ? AND TENANT_ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setInt(1, deviceId); + stmt.setString(2, currentOwner); + stmt.setInt(3, tenantId); + rs = stmt.executeQuery(); + if (rs.next()) { + enrolmentInfo = this.loadEnrolment(rs); + } + return enrolmentInfo; + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while retrieving the enrolment " + + "information of user '" + currentOwner + "' upon device '" + deviceId + "'", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + } + } + + @Override + public EnrolmentInfo getEnrollment(int deviceId, int tenantId) throws DeviceManagementDAOException { + Connection conn; + PreparedStatement stmt = null; + ResultSet rs = null; + EnrolmentInfo enrolmentInfo = null; + try { + conn = this.getConnection(); + String sql = "SELECT ID, DEVICE_ID, OWNER, OWNERSHIP, STATUS, IS_TRANSFERRED, DATE_OF_ENROLMENT, " + + "DATE_OF_LAST_UPDATE, TENANT_ID FROM DM_ENROLMENT WHERE DEVICE_ID = ? AND TENANT_ID = ? " + + "ORDER BY DATE_OF_LAST_UPDATE DESC"; + stmt = conn.prepareStatement(sql); + stmt.setInt(1, deviceId); + stmt.setInt(2, tenantId); + rs = stmt.executeQuery(); + if (rs.next()) { + enrolmentInfo = this.loadEnrolment(rs); + } + return enrolmentInfo; + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while retrieving the enrolment " + + "information of device '" + deviceId + "'", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + } + } + + @Override + public List getEnrollmentsOfUser(int deviceId, String user, int tenantId) + throws DeviceManagementDAOException { + List enrolmentInfos = new ArrayList<>(); + Connection conn; + PreparedStatement stmt = null; + ResultSet rs = null; + EnrolmentInfo enrolmentInfo = null; + try { + conn = this.getConnection(); + String sql = "SELECT ID, DEVICE_ID, OWNER, OWNERSHIP, STATUS, IS_TRANSFERRED, DATE_OF_ENROLMENT, " + + "DATE_OF_LAST_UPDATE, TENANT_ID FROM DM_ENROLMENT WHERE DEVICE_ID = ? AND OWNER = ? AND TENANT_ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setInt(1, deviceId); + stmt.setString(2, user); + stmt.setInt(3, tenantId); + rs = stmt.executeQuery(); + while (rs.next()) { + enrolmentInfo = this.loadEnrolment(rs); + enrolmentInfos.add(enrolmentInfo); + } + return enrolmentInfos; + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while retrieving the enrolments " + + "information of user '" + user + "' upon device '" + deviceId + "'", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + } + } + + @Override + public boolean updateOwnerOfEnrollment(List devices, String owner, int tenantId) + throws DeviceManagementDAOException { + try { + Connection conn = this.getConnection(); + boolean updateStatus = true; + String sql = "UPDATE DM_ENROLMENT " + + "SET OWNER = ?, IS_TRANSFERRED = ?, DATE_OF_LAST_UPDATE = ? " + + "WHERE ID = ? AND TENANT_ID = ?"; + try (PreparedStatement ps = conn.prepareStatement(sql)) { + if (conn.getMetaData().supportsBatchUpdates()) { + for (Device device : devices) { + ps.setString(1, owner); + ps.setBoolean(2, device.getEnrolmentInfo().isTransferred()); + ps.setTimestamp(3, new Timestamp(new Date().getTime())); + ps.setInt(4, device.getEnrolmentInfo().getId()); + ps.setInt(5, tenantId); + ps.addBatch(); + } + int[] batchResult = ps.executeBatch(); + for (int i : batchResult) { + if (i == 0 || i == Statement.SUCCESS_NO_INFO || i == Statement.EXECUTE_FAILED) { + updateStatus = false; + break; + } + } + } else { + for (Device device : devices) { + ps.setString(1, owner); + ps.setBoolean(2, device.getEnrolmentInfo().isTransferred()); + ps.setInt(3, device.getId()); + ps.setInt(4, tenantId); + if (ps.executeUpdate() == 0) { + updateStatus = false; + break; + } + } + } + } + return updateStatus; + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while obtaining the DB connection to update the " + + "owner of the device enrollment.", e); + } + } + + private Connection getConnection() throws SQLException { + return DeviceManagementDAOFactory.getConnection(); + } + + private EnrolmentInfo loadEnrolment(ResultSet rs) throws SQLException { + EnrolmentInfo enrolmentInfo = new EnrolmentInfo(); + enrolmentInfo.setOwner(rs.getString("OWNER")); + enrolmentInfo.setOwnership(EnrolmentInfo.OwnerShip.valueOf(rs.getString("OWNERSHIP"))); + enrolmentInfo.setTransferred(rs.getBoolean("IS_TRANSFERRED")); + enrolmentInfo.setDateOfEnrolment(rs.getTimestamp("DATE_OF_ENROLMENT").getTime()); + enrolmentInfo.setDateOfLastUpdate(rs.getTimestamp("DATE_OF_LAST_UPDATE").getTime()); + enrolmentInfo.setStatus(EnrolmentInfo.Status.valueOf(rs.getString("STATUS"))); + enrolmentInfo.setId(rs.getInt("ID")); + return enrolmentInfo; + } + +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/dao/DeviceStatusPersistenceTests.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/dao/DeviceStatusPersistenceTests.java index 65c22e11613..b2a8903c7fb 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/dao/DeviceStatusPersistenceTests.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/dao/DeviceStatusPersistenceTests.java @@ -39,9 +39,15 @@ import static org.wso2.carbon.device.mgt.common.EnrolmentInfo.Status.*; public class DeviceStatusPersistenceTests extends BaseDeviceManagementTest { private static final Log log = LogFactory.getLog(DeviceStatusPersistenceTests.class); - private EnrollmentDAO enrollmentDAO = DeviceManagementDAOFactory.getEnrollmentDAO(); + EnrollmentDAO enrollmentDAO; private DeviceStatusDAO deviceStatusDAO = DeviceManagementDAOFactory.getDeviceStatusDAO(); + @BeforeClass + @Override + public void init() throws Exception { + enrollmentDAO = DeviceManagementDAOFactory.getEnrollmentDAO(); + } + /** * Validate that the list of statuses received match the statuses * @param device @@ -245,10 +251,4 @@ public class DeviceStatusPersistenceTests extends BaseDeviceManagementTest { } return false; } - - @BeforeClass - @Override - public void init() throws Exception { - - } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/dao/EnrolmentPersistenceTests.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/dao/EnrolmentPersistenceTests.java index 9497324798e..10bf0a1b641 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/dao/EnrolmentPersistenceTests.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/dao/EnrolmentPersistenceTests.java @@ -33,7 +33,14 @@ import java.sql.SQLException; public class EnrolmentPersistenceTests extends BaseDeviceManagementTest { private static final Log log = LogFactory.getLog(EnrolmentPersistenceTests.class); - private EnrollmentDAO enrollmentDAO = DeviceManagementDAOFactory.getEnrollmentDAO(); + EnrollmentDAO enrollmentDAO; + + @BeforeClass + @Override + public void init() throws Exception { + this.initDataSource(); + enrollmentDAO = DeviceManagementDAOFactory.getEnrollmentDAO(); + } @Test public void testAddEnrolment() { @@ -86,10 +93,4 @@ public class EnrolmentPersistenceTests extends BaseDeviceManagementTest { } return enrolmentInfo; } - - @BeforeClass - @Override - public void init() throws Exception { - this.initDataSource(); - } } diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mssql.sql b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mssql.sql index d43294bd34e..c8b809ae48b 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mssql.sql +++ b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mssql.sql @@ -10,6 +10,13 @@ CREATE TABLE DM_DEVICE_TYPE ( CONSTRAINT DEVICE_TYPE_NAME UNIQUE(NAME, PROVIDER_TENANT_ID) ); +IF NOT EXISTS (SELECT * FROM SYS.INDEXES WHERE NAME = 'IDX_DEVICE_TYPE' AND OBJECT_ID = OBJECT_ID('DM_DEVICE_TYPE')) +CREATE INDEX IDX_DEVICE_TYPE ON DM_DEVICE_TYPE (NAME, PROVIDER_TENANT_ID); +IF NOT EXISTS (SELECT * FROM SYS.INDEXES WHERE NAME = 'IDX_DEVICE_NAME' AND OBJECT_ID = OBJECT_ID('DM_DEVICE_TYPE')) +CREATE INDEX IDX_DEVICE_NAME ON DM_DEVICE_TYPE (NAME); +IF NOT EXISTS (SELECT * FROM SYS.INDEXES WHERE NAME = 'IDX_DEVICE_TYPE_DEVICE_NAME' AND OBJECT_ID = OBJECT_ID('DM_DEVICE_TYPE')) +CREATE INDEX IDX_DEVICE_TYPE_DEVICE_NAME ON DM_DEVICE_TYPE (ID, NAME); + IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[DM_DEVICE_CERTIFICATE]') AND TYPE IN (N'U')) CREATE TABLE DM_DEVICE_CERTIFICATE ( ID INTEGER IDENTITY(1,1) NOT NULL, @@ -165,6 +172,13 @@ CREATE TABLE DM_ENROLMENT_OP_MAPPING ( PUSH_NOTIFICATION_STATUS VARCHAR(50) NULL, CREATED_TIMESTAMP BIGINT NOT NULL, UPDATED_TIMESTAMP BIGINT NOT NULL, + OPERATION_CODE VARCHAR(50) NOT NULL, + INITIATED_BY VARCHAR(100) NULL, + TYPE VARCHAR(20) NOT NULL, + DEVICE_ID INTEGER DEFAULT NULL, + DEVICE_TYPE VARCHAR(300) NOT NULL, + DEVICE_IDENTIFICATION VARCHAR(300) DEFAULT NULL, + TENANT_ID INTEGER DEFAULT 0, PRIMARY KEY (ID), CONSTRAINT FK_DM_DEVICE_OPERATION_MAPPING_DEVICE FOREIGN KEY (ENROLMENT_ID) REFERENCES DM_ENROLMENT (ID) ON DELETE NO ACTION ON UPDATE NO ACTION, @@ -178,6 +192,8 @@ IF NOT EXISTS (SELECT * FROM SYS.INDEXES WHERE NAME = 'IDX_EN_OP_MAPPING_EN_ID' CREATE INDEX IDX_EN_OP_MAPPING_EN_ID ON DM_ENROLMENT_OP_MAPPING(ENROLMENT_ID); IF NOT EXISTS (SELECT * FROM SYS.INDEXES WHERE NAME = 'IDX_EN_OP_MAPPING_OP_ID' AND OBJECT_ID = OBJECT_ID('DM_ENROLMENT_OP_MAPPING')) CREATE INDEX IDX_EN_OP_MAPPING_OP_ID ON DM_ENROLMENT_OP_MAPPING(OPERATION_ID); +IF NOT EXISTS (SELECT * FROM SYS.INDEXES WHERE NAME = 'IDX_EN_OP_MAPPING_EN_ID_STATUS' AND OBJECT_ID = OBJECT_ID('DM_ENROLMENT_OP_MAPPING')) +CREATE INDEX IDX_EN_OP_MAPPING_EN_ID_STATUS ON DM_ENROLMENT_OP_MAPPING(ENROLMENT_ID, STATUS); IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[DM_DEVICE_OPERATION_RESPONSE]') AND TYPE IN (N'U')) CREATE TABLE DM_DEVICE_OPERATION_RESPONSE ( From 36bae5e3c197fb929ab427f968c7f78e6119bc50 Mon Sep 17 00:00:00 2001 From: Kavin Prathaban Date: Tue, 25 Apr 2023 07:54:05 +0000 Subject: [PATCH 4/4] Fix geofences not loading with MSSQL db (#75) ## Purpose * Fixes https://roadmap.entgra.net/issues/9987 ## Description * Fix geofences page not loading when starting the pack with MSSQL databases. Co-authored-by: prathabanKavin Co-authored-by: Pahansith Gunathilake Reviewed-on: https://repository.entgra.net/community/device-mgt-core/pulls/75 Co-authored-by: Kavin Prathaban Co-committed-by: Kavin Prathaban --- .../core/dao/EventManagementDAOFactory.java | 17 +- ...Impl.java => AbstractGeofenceDAOImpl.java} | 5 +- .../impl/geofence/GenericGeofenceDAOImpl.java | 637 ++++++++++++++++++ .../geofence/SQLServerGeofenceDAOImpl.java | 109 +++ 4 files changed, 764 insertions(+), 4 deletions(-) rename components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/{GeofenceDAOImpl.java => AbstractGeofenceDAOImpl.java} (99%) create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/geofence/GenericGeofenceDAOImpl.java create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/geofence/SQLServerGeofenceDAOImpl.java diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/EventManagementDAOFactory.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/EventManagementDAOFactory.java index 754b5190041..09e5353fa61 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/EventManagementDAOFactory.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/EventManagementDAOFactory.java @@ -29,6 +29,8 @@ import org.wso2.carbon.device.mgt.core.config.datasource.JNDILookupDefinition; import org.wso2.carbon.device.mgt.core.dao.impl.*; import org.wso2.carbon.device.mgt.core.dao.impl.event.GenericEventConfigDAOImpl; import org.wso2.carbon.device.mgt.core.dao.impl.event.H2EventConfigDAOImpl; +import org.wso2.carbon.device.mgt.core.dao.impl.geofence.GenericGeofenceDAOImpl; +import org.wso2.carbon.device.mgt.core.dao.impl.geofence.SQLServerGeofenceDAOImpl; import org.wso2.carbon.device.mgt.core.dao.util.DeviceManagementDAOUtil; import javax.sql.DataSource; @@ -45,7 +47,20 @@ public class EventManagementDAOFactory { public static GeofenceDAO getGeofenceDAO() { - return new GeofenceDAOImpl(); + if (databaseEngine != null) { + switch (databaseEngine) { + case DeviceManagementConstants.DataBaseTypes.DB_TYPE_MSSQL: + return new SQLServerGeofenceDAOImpl(); + case DeviceManagementConstants.DataBaseTypes.DB_TYPE_POSTGRESQL: + case DeviceManagementConstants.DataBaseTypes.DB_TYPE_ORACLE: + case DeviceManagementConstants.DataBaseTypes.DB_TYPE_MYSQL: + case DeviceManagementConstants.DataBaseTypes.DB_TYPE_H2: + return new GenericGeofenceDAOImpl(); + default: + throw new UnsupportedDatabaseEngineException("Unsupported database engine : " + databaseEngine); + } + } + throw new IllegalStateException("Database engine has not initialized properly."); } public static EventConfigDAO getEventConfigDAO() { diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/GeofenceDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractGeofenceDAOImpl.java similarity index 99% rename from components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/GeofenceDAOImpl.java rename to components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractGeofenceDAOImpl.java index e845a43da92..4c8cd12e7e5 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/GeofenceDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractGeofenceDAOImpl.java @@ -25,7 +25,6 @@ import org.wso2.carbon.device.mgt.common.PaginationRequest; import org.wso2.carbon.device.mgt.common.event.config.EventConfig; import org.wso2.carbon.device.mgt.common.geo.service.GeofenceData; 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.EventManagementDAOFactory; import org.wso2.carbon.device.mgt.core.dao.GeofenceDAO; import org.wso2.carbon.device.mgt.core.dto.event.config.GeoFenceGroupMap; @@ -45,8 +44,8 @@ import java.util.List; import java.util.Map; import java.util.Set; -public class GeofenceDAOImpl implements GeofenceDAO { - private static final Log log = LogFactory.getLog(GeofenceDAOImpl.class); +public abstract class AbstractGeofenceDAOImpl implements GeofenceDAO { + private static final Log log = LogFactory.getLog(AbstractGeofenceDAOImpl.class); @Override public GeofenceData saveGeofence(GeofenceData geofenceData) throws DeviceManagementDAOException { try { diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/geofence/GenericGeofenceDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/geofence/GenericGeofenceDAOImpl.java new file mode 100644 index 00000000000..b7784a34800 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/geofence/GenericGeofenceDAOImpl.java @@ -0,0 +1,637 @@ +/* + * 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.core.dao.impl.geofence; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.device.mgt.common.DeviceManagementConstants; +import org.wso2.carbon.device.mgt.common.PaginationRequest; +import org.wso2.carbon.device.mgt.common.event.config.EventConfig; +import org.wso2.carbon.device.mgt.common.geo.service.GeofenceData; +import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOException; +import org.wso2.carbon.device.mgt.core.dao.EventManagementDAOFactory; +import org.wso2.carbon.device.mgt.core.dao.GeofenceDAO; +import org.wso2.carbon.device.mgt.core.dao.impl.AbstractGeofenceDAOImpl; +import org.wso2.carbon.device.mgt.core.dto.event.config.GeoFenceGroupMap; + +import java.sql.*; +import java.util.Date; +import java.util.*; + +public class GenericGeofenceDAOImpl extends AbstractGeofenceDAOImpl { + private static final Log log = LogFactory.getLog(GenericGeofenceDAOImpl.class); + @Override + public GeofenceData saveGeofence(GeofenceData geofenceData) throws DeviceManagementDAOException { + try { + Connection conn = this.getConnection(); + String sql = "INSERT INTO DM_GEOFENCE(" + + "FENCE_NAME, " + + "DESCRIPTION, " + + "LATITUDE, " + + "LONGITUDE, " + + "RADIUS, " + + "GEO_JSON, " + + "FENCE_SHAPE, " + + "CREATED_TIMESTAMP, " + + "OWNER, " + + "TENANT_ID) " + + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + try (PreparedStatement stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) { + stmt.setString(1, geofenceData.getFenceName()); + stmt.setString(2, geofenceData.getDescription()); + stmt.setDouble(3, geofenceData.getLatitude()); + stmt.setDouble(4, geofenceData.getLongitude()); + stmt.setFloat(5, geofenceData.getRadius()); + stmt.setString(6, geofenceData.getGeoJson()); + stmt.setString(7, geofenceData.getFenceShape()); + stmt.setTimestamp(8, new Timestamp(new Date().getTime())); + stmt.setString(9, geofenceData.getOwner()); + stmt.setInt(10, geofenceData.getTenantId()); + if (stmt.executeUpdate() > 0) { + ResultSet generatedKeys = stmt.getGeneratedKeys(); + if (generatedKeys.next()) { + geofenceData.setId(generatedKeys.getInt(1)); + } + } + return geofenceData; + } + } catch (SQLException e) { + String msg = "Error occurred while creating Geofence for the tenant id "+geofenceData.getTenantId(); + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + @Override + public GeofenceData getGeofence(int fenceId) throws DeviceManagementDAOException { + try { + Connection conn = this.getConnection(); + GeofenceData geofenceData = null; + String sql = "SELECT " + + "ID, " + + "FENCE_NAME, " + + "DESCRIPTION, " + + "LATITUDE, " + + "LONGITUDE, " + + "RADIUS, " + + "GEO_JSON, " + + "FENCE_SHAPE, " + + "OWNER, " + + "TENANT_ID " + + "FROM DM_GEOFENCE " + + "WHERE ID = ?"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setInt(1, fenceId); + try (ResultSet rst = stmt.executeQuery()) { + List geofenceDataList = extractGeofenceData(rst); + if (!geofenceDataList.isEmpty()) { + geofenceData = geofenceDataList.get(0); + } + } + } + return geofenceData; + } catch (SQLException e) { + String msg = "Error occurred while retrieving Geofence with id "+fenceId; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + @Override + public List getGeoFencesOfTenant(PaginationRequest request, int tenantId) + throws DeviceManagementDAOException { + try { + Connection conn = this.getConnection(); + boolean isNameProvided = false; + List geofenceData; + String sql = "SELECT " + + "ID, " + + "FENCE_NAME, " + + "DESCRIPTION, " + + "LATITUDE, " + + "LONGITUDE, " + + "RADIUS, " + + "GEO_JSON, " + + "FENCE_SHAPE, " + + "OWNER, " + + "TENANT_ID " + + "FROM DM_GEOFENCE " + + "WHERE TENANT_ID = ? "; + + if (request.getProperty(DeviceManagementConstants.GeoServices.FENCE_NAME) != null) { + sql += "AND FENCE_NAME LIKE ?"; + isNameProvided = true; + } + sql += "LIMIT ? OFFSET ?"; + int index = 1; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setInt(index++, tenantId); + if (isNameProvided) { + stmt.setString(index++, request.getProperty(DeviceManagementConstants.GeoServices.FENCE_NAME).toString() + "%"); + } + stmt.setInt(index++, request.getRowCount()); + stmt.setInt(index, request.getStartIndex()); + try (ResultSet rst = stmt.executeQuery()) { + geofenceData = extractGeofenceData(rst); + } + } + return geofenceData; + } catch (SQLException e) { + String msg = "Error occurred while retrieving Geofence of the tenant " + tenantId; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + @Override + public List getGeoFencesOfTenant(String fenceName, int tenantId) + throws DeviceManagementDAOException { + try { + Connection conn = this.getConnection(); + List geofenceData; + String sql = "SELECT " + + "ID, " + + "FENCE_NAME, " + + "DESCRIPTION, " + + "LATITUDE, " + + "LONGITUDE, " + + "RADIUS, " + + "GEO_JSON, " + + "FENCE_SHAPE, " + + "OWNER, " + + "TENANT_ID " + + "FROM DM_GEOFENCE " + + "WHERE FENCE_NAME LIKE ?" + + "AND TENANT_ID = ? "; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setString(1, fenceName + "%"); + stmt.setInt(2, tenantId); + try (ResultSet rst = stmt.executeQuery()) { + geofenceData = extractGeofenceData(rst); + } + } + return geofenceData; + } catch (SQLException e) { + String msg = "Error occurred while retrieving Geofence of the tenant " + tenantId; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + @Override + public List getGeoFencesOfTenant(int tenantId) + throws DeviceManagementDAOException { + try { + Connection conn = this.getConnection(); + List geofenceData; + String sql = "SELECT " + + "ID, " + + "FENCE_NAME, " + + "DESCRIPTION, " + + "LATITUDE, " + + "LONGITUDE, " + + "RADIUS, " + + "GEO_JSON, " + + "FENCE_SHAPE, " + + "OWNER, " + + "TENANT_ID " + + "FROM DM_GEOFENCE " + + "WHERE TENANT_ID = ? "; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setInt(1, tenantId); + try (ResultSet rst = stmt.executeQuery()) { + geofenceData = extractGeofenceData(rst); + } + } + return geofenceData; + } catch (SQLException e) { + String msg = "Error occurred while retrieving Geofence of the tenant " + tenantId; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + @Override + public int deleteGeofenceById(int fenceId) throws DeviceManagementDAOException { + try { + Connection conn = this.getConnection(); + String sql = "DELETE FROM DM_GEOFENCE WHERE ID = ?"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setInt(1, fenceId); + return stmt.executeUpdate(); + } + } catch (SQLException e) { + String msg = "Error occurred while deleting Geofence with ID " + fenceId; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + @Override + public int updateGeofence(GeofenceData geofenceData, int fenceId) throws DeviceManagementDAOException { + try { + Connection conn = this.getConnection(); + String sql = "UPDATE DM_GEOFENCE SET " + + "FENCE_NAME = ?, " + + "DESCRIPTION = ?, " + + "LATITUDE = ?, " + + "LONGITUDE = ?, " + + "RADIUS = ?, " + + "GEO_JSON = ?, " + + "FENCE_SHAPE = ? " + + "WHERE ID = ?"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setString(1, geofenceData.getFenceName()); + stmt.setString(2, geofenceData.getDescription()); + stmt.setDouble(3, geofenceData.getLatitude()); + stmt.setDouble(4, geofenceData.getLongitude()); + stmt.setFloat(5, geofenceData.getRadius()); + stmt.setString(6, geofenceData.getGeoJson()); + stmt.setString(7, geofenceData.getFenceShape()); + stmt.setInt(8, fenceId); + return stmt.executeUpdate(); + } + } catch (SQLException e) { + String msg = "Error occurred while updating Geofence record with id " + fenceId; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + @Override + public boolean createGeofenceGroupMapping(GeofenceData geofenceData, List groupIds) throws DeviceManagementDAOException { + try { + Connection conn = this.getConnection(); + String sql = "INSERT INTO DM_GEOFENCE_GROUP_MAPPING(" + + "FENCE_ID, " + + "GROUP_ID) " + + "VALUES (?, ?)"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + for (Integer groupId : groupIds) { + stmt.setInt(1, geofenceData.getId()); + stmt.setInt(2, groupId); + stmt.addBatch(); + } + return stmt.executeBatch().length > 0; + } + } catch (SQLException e) { + String msg = "Error occurred while creating geofence group mapping records"; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + private Connection getConnection() throws SQLException { + return EventManagementDAOFactory.getConnection(); + } + + private List extractGeofenceData(ResultSet rst) throws SQLException { + List geofenceDataList = new ArrayList<>(); + while (rst.next()) { + GeofenceData geofenceData = new GeofenceData(); + geofenceData.setId(rst.getInt("ID")); + geofenceData.setFenceName(rst.getString("FENCE_NAME")); + geofenceData.setDescription(rst.getString("DESCRIPTION")); + geofenceData.setLatitude(rst.getDouble("LATITUDE")); + geofenceData.setLongitude(rst.getDouble("LONGITUDE")); + geofenceData.setRadius(rst.getFloat("RADIUS")); + geofenceData.setGeoJson(rst.getString("GEO_JSON")); + geofenceData.setFenceShape(rst.getString("FENCE_SHAPE")); + geofenceData.setOwner(rst.getString("OWNER")); + geofenceData.setTenantId(rst.getInt("TENANT_ID")); + geofenceDataList.add(geofenceData); + } + return geofenceDataList; + } + + @Override + public List getGroupIdsOfGeoFence(int fenceId) throws DeviceManagementDAOException { + try { + Connection conn = this.getConnection(); + String sql = "SELECT " + + "GROUP_ID " + + "FROM DM_GEOFENCE_GROUP_MAPPING " + + "WHERE FENCE_ID = ? "; + List groupIds = new ArrayList<>(); + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setInt(1, fenceId); + try (ResultSet rst = stmt.executeQuery()) { + while (rst.next()) { + groupIds.add(rst.getInt(1)); + } + } + } + return groupIds; + } catch (SQLException e) { + String msg = "Error occurred while fetching group IDs of the fence " + fenceId; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + @Override + public void deleteGeofenceGroupMapping(List groupIdsToDelete, int fenceId) throws DeviceManagementDAOException { + try { + Connection conn = this.getConnection(); + String sql = "DELETE FROM DM_GEOFENCE_GROUP_MAPPING WHERE GROUP_ID = ? AND FENCE_ID = ?"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + for (Integer groupId : groupIdsToDelete) { + stmt.setInt(1, groupId); + stmt.setInt(2, fenceId); + stmt.addBatch(); + } + stmt.executeBatch(); + } + } catch (SQLException e) { + String msg = "Error occurred while deleting Geofence group mapping records"; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + @Override + public void createGeofenceEventMapping(int fenceId, List eventIds) throws DeviceManagementDAOException { + try { + Connection conn = this.getConnection(); + String sql = "INSERT INTO DM_GEOFENCE_EVENT_MAPPING(" + + "FENCE_ID, "+ + "EVENT_ID) " + + "VALUES (?, ?)"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + for (Integer createdEventId : eventIds) { + stmt.setInt(1, fenceId); + stmt.setInt(2, createdEventId); + stmt.addBatch(); + } + stmt.executeBatch(); + } + } catch (SQLException e) { + String msg = "Error occurred while creating geofence event group mapping records"; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + @Override + public void deleteGeofenceEventMapping(List removedEventIdList) throws DeviceManagementDAOException { + try { + Connection conn = this.getConnection(); + String sql = "DELETE FROM DM_GEOFENCE_EVENT_MAPPING WHERE EVENT_ID = ?"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + for (Integer eventId : removedEventIdList) { + stmt.setInt(1, eventId); + stmt.addBatch(); + } + stmt.executeBatch(); + } + } catch (SQLException e) { + String msg = "Error occurred while deleting Geofence event mapping records"; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + @Override + public Map> getEventsOfGeoFences(List geofenceIds) throws DeviceManagementDAOException { + try { + Map> geoFenceEventMap = new HashMap<>(); + if (geofenceIds.isEmpty()) { + return geoFenceEventMap; + } + Connection conn = this.getConnection(); + String sql = "SELECT " + + "E.ID AS EVENT_ID, " + + "M.FENCE_ID AS FENCE_ID, " + + "EVENT_SOURCE, " + + "EVENT_LOGIC, " + + "ACTIONS " + + "FROM DM_DEVICE_EVENT E, DM_GEOFENCE_EVENT_MAPPING M " + + "WHERE E.ID = M.EVENT_ID " + + "AND M.FENCE_ID IN (%s)"; + String inClause = String.join(", ", Collections.nCopies(geofenceIds.size(), "?")); + sql = String.format(sql, inClause); + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + int index = 1; + for (Integer geofenceId : geofenceIds) { + stmt.setInt(index++, geofenceId); + } + ResultSet resultSet = stmt.executeQuery(); + while (resultSet.next()) { + int fenceId = resultSet.getInt("FENCE_ID"); + List eventConfigList = geoFenceEventMap.get(fenceId); + if (eventConfigList == null) { + eventConfigList = new ArrayList<>(); + } + EventConfig event = new EventConfig(); + event.setEventId(resultSet.getInt("EVENT_ID")); + event.setEventSource(resultSet.getString("EVENT_SOURCE")); + event.setEventLogic(resultSet.getString("EVENT_LOGIC")); + event.setActions(resultSet.getString("ACTIONS")); + eventConfigList.add(event); + geoFenceEventMap.put(fenceId, eventConfigList); + } + return geoFenceEventMap; + } + } catch (SQLException e) { + String msg = "Error occurred while updating Geofence record with id "; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + @Override + public List getEventsOfGeoFence(int geofenceId) throws DeviceManagementDAOException { + try { + List eventList = new ArrayList<>(); + Connection conn = this.getConnection(); + String sql = "SELECT " + + "E.ID AS EVENT_ID, " + + "EVENT_SOURCE, " + + "EVENT_LOGIC, " + + "ACTIONS " + + "FROM DM_DEVICE_EVENT E, DM_GEOFENCE_EVENT_MAPPING G " + + "WHERE E.ID = G.EVENT_ID " + + "AND G.FENCE_ID = ?"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setInt(1, geofenceId); + return getEventConfigs(stmt); + } + } catch (SQLException e) { + String msg = "Error occurred while updating Geofence record with id "; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + @Override + public Set getGroupIdsOfGeoFences(List fenceIds) throws DeviceManagementDAOException { + try { + Set geoFenceGroupSet = new HashSet<>(); + if (fenceIds.isEmpty()) { + return geoFenceGroupSet; + } + Connection conn = this.getConnection(); + String sql = "SELECT " + + "FENCE_ID, " + + "M.GROUP_ID, " + + "G.GROUP_NAME " + + "FROM DM_GEOFENCE_GROUP_MAPPING M, DM_GROUP G " + + "WHERE M.GROUP_ID = G.ID " + + "AND FENCE_ID IN (%s)"; + String inClause = String.join(", ", Collections.nCopies(fenceIds.size(), "?")); + sql = String.format(sql, inClause); + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + int index = 1; + for (Integer fenceId : fenceIds) { + stmt.setInt(index++, fenceId); + } + ResultSet rst = stmt.executeQuery(); + while (rst.next()) { + GeoFenceGroupMap geoFenceGroupMap = new GeoFenceGroupMap(); + geoFenceGroupMap.setFenceId(rst.getInt("FENCE_ID")); + geoFenceGroupMap.setGroupId(rst.getInt("GROUP_ID")); + geoFenceGroupMap.setGroupName(rst.getString("GROUP_NAME")); + geoFenceGroupSet.add(geoFenceGroupMap); + } + } + return geoFenceGroupSet; + } catch (SQLException e) { + String msg = "Error occurred while fetching group IDs of the fences"; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + /** + * Retrieve the geofence event extracted from the DB + * @param stmt prepared statement to retrieve data from the DB + * @return Retrieved Event list from the DB + * @throws SQLException for the errors occur while accessing the DB + */ + private List getEventConfigs(PreparedStatement stmt) throws SQLException { + List eventList = new ArrayList<>(); + ResultSet resultSet = stmt.executeQuery(); + EventConfig event; + while (resultSet.next()) { + event = new EventConfig(); + event.setEventId(resultSet.getInt("EVENT_ID")); + event.setEventSource(resultSet.getString("EVENT_SOURCE")); + event.setEventLogic(resultSet.getString("EVENT_LOGIC")); + event.setActions(resultSet.getString("ACTIONS")); + eventList.add(event); + } + return eventList; + } + + @Override + public List getGeoFences(int groupId, int tenantId) throws DeviceManagementDAOException { + try { + Connection conn = this.getConnection(); + String sql = "SELECT " + + "G.ID AS FENCE_ID, " + + "FENCE_NAME, " + + "DESCRIPTION, " + + "LATITUDE," + + "LONGITUDE, " + + "RADIUS, " + + "GEO_JSON, " + + "FENCE_SHAPE " + + "FROM DM_GEOFENCE G, DM_GEOFENCE_GROUP_MAPPING M " + + "WHERE M.GROUP_ID = ? AND TENANT_ID = ? " + + "GROUP BY G.ID"; + + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setInt(1, groupId); + stmt.setInt(2, tenantId); + ResultSet rst = stmt.executeQuery(); + List geofenceDataList = new ArrayList<>(); + while (rst.next()) { + GeofenceData geofenceData = new GeofenceData(); + geofenceData.setId(rst.getInt("FENCE_ID")); + geofenceData.setFenceName(rst.getString("FENCE_NAME")); + geofenceData.setDescription(rst.getString("DESCRIPTION")); + geofenceData.setLatitude(rst.getDouble("LATITUDE")); + geofenceData.setLongitude(rst.getDouble("LONGITUDE")); + geofenceData.setRadius(rst.getFloat("RADIUS")); + geofenceData.setGeoJson(rst.getString("GEO_JSON")); + geofenceData.setFenceShape(rst.getString("FENCE_SHAPE")); + geofenceDataList.add(geofenceData); + } + return geofenceDataList; + } + } catch (SQLException e) { + String msg = "Error occurred while retrieving Geo fences of group " + groupId + + " and tenant " + tenantId; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + @Override + public GeofenceData getGeofence(int fenceId, boolean requireGroupData) throws DeviceManagementDAOException { + if (!requireGroupData) { + return getGeofence(fenceId); + } + + try { + Connection con = this.getConnection(); + String sql = "SELECT " + + "G.ID AS FENCE_ID, " + + "FENCE_NAME, " + + "G.DESCRIPTION, " + + "LATITUDE, " + + "LONGITUDE, " + + "RADIUS, " + + "GEO_JSON, " + + "FENCE_SHAPE, " + + "M.GROUP_ID AS GROUP_ID, " + + "GR.GROUP_NAME " + + "FROM DM_GEOFENCE G, DM_GEOFENCE_GROUP_MAPPING M, DM_GROUP GR " + + "WHERE G.ID = M.FENCE_ID " + + "AND M.GROUP_ID = GR.ID " + + "AND G.ID = ?"; + try (PreparedStatement stmt = con.prepareStatement(sql)){ + stmt.setInt(1, fenceId); + ResultSet rst = stmt.executeQuery(); + Map groupMap = new HashMap<>(); + GeofenceData geofenceData = null; + while (rst.next()) { + groupMap.put(rst.getInt("GROUP_ID"), rst.getString("GROUP_NAME")); + if (rst.isLast()) { + geofenceData = new GeofenceData(); + geofenceData.setId(rst.getInt("FENCE_ID")); + geofenceData.setFenceName(rst.getString("FENCE_NAME")); + geofenceData.setDescription(rst.getString("DESCRIPTION")); + geofenceData.setLatitude(rst.getDouble("LATITUDE")); + geofenceData.setLongitude(rst.getDouble("LONGITUDE")); + geofenceData.setRadius(rst.getFloat("RADIUS")); + geofenceData.setGeoJson(rst.getString("GEO_JSON")); + geofenceData.setFenceShape(rst.getString("FENCE_SHAPE")); + geofenceData.setGroupData(groupMap); + } + } + return geofenceData; + } + } catch (SQLException e) { + String msg = "Error occurred while retrieving Geo fence data " + fenceId; + 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/geofence/SQLServerGeofenceDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/geofence/SQLServerGeofenceDAOImpl.java new file mode 100644 index 00000000000..7fe050a477f --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/geofence/SQLServerGeofenceDAOImpl.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2023, 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.core.dao.impl.geofence; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.device.mgt.common.DeviceManagementConstants; +import org.wso2.carbon.device.mgt.common.PaginationRequest; +import org.wso2.carbon.device.mgt.common.event.config.EventConfig; +import org.wso2.carbon.device.mgt.common.geo.service.GeofenceData; +import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOException; +import org.wso2.carbon.device.mgt.core.dao.EventManagementDAOFactory; +import org.wso2.carbon.device.mgt.core.dao.GeofenceDAO; +import org.wso2.carbon.device.mgt.core.dao.impl.AbstractGeofenceDAOImpl; +import org.wso2.carbon.device.mgt.core.dto.event.config.GeoFenceGroupMap; + +import java.sql.*; +import java.util.Date; +import java.util.*; + +public class SQLServerGeofenceDAOImpl extends AbstractGeofenceDAOImpl { + private static final Log log = LogFactory.getLog(SQLServerGeofenceDAOImpl.class); + + @Override + public List getGeoFencesOfTenant(PaginationRequest request, int tenantId) + throws DeviceManagementDAOException { + try { + Connection conn = this.getConnection(); + boolean isNameProvided = false; + List geofenceData; + String sql = "SELECT " + + "ID, " + + "FENCE_NAME, " + + "DESCRIPTION, " + + "LATITUDE, " + + "LONGITUDE, " + + "RADIUS, " + + "GEO_JSON, " + + "FENCE_SHAPE, " + + "OWNER, " + + "TENANT_ID " + + "FROM DM_GEOFENCE " + + "WHERE TENANT_ID = ? "; + + if (request.getProperty(DeviceManagementConstants.GeoServices.FENCE_NAME) != null) { + sql += "AND FENCE_NAME LIKE ?"; + isNameProvided = true; + } + sql += "ORDER BY FENCE_NAME "; + sql += "OFFSET ? ROWS FETCH NEXT ? ROWS ONLY"; + int index = 1; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setInt(index++, tenantId); + if (isNameProvided) { + stmt.setString(index++, request.getProperty(DeviceManagementConstants.GeoServices.FENCE_NAME).toString() + "%"); + } + stmt.setInt(index++, request.getStartIndex()); + stmt.setInt(index, request.getRowCount()); + try (ResultSet rst = stmt.executeQuery()) { + geofenceData = extractGeofenceData(rst); + } + } + return geofenceData; + } catch (SQLException e) { + String msg = "Error occurred while retrieving Geofence of the tenant " + tenantId; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + private Connection getConnection() throws SQLException { + return EventManagementDAOFactory.getConnection(); + } + + private List extractGeofenceData(ResultSet rst) throws SQLException { + List geofenceDataList = new ArrayList<>(); + while (rst.next()) { + GeofenceData geofenceData = new GeofenceData(); + geofenceData.setId(rst.getInt("ID")); + geofenceData.setFenceName(rst.getString("FENCE_NAME")); + geofenceData.setDescription(rst.getString("DESCRIPTION")); + geofenceData.setLatitude(rst.getDouble("LATITUDE")); + geofenceData.setLongitude(rst.getDouble("LONGITUDE")); + geofenceData.setRadius(rst.getFloat("RADIUS")); + geofenceData.setGeoJson(rst.getString("GEO_JSON")); + geofenceData.setFenceShape(rst.getString("FENCE_SHAPE")); + geofenceData.setOwner(rst.getString("OWNER")); + geofenceData.setTenantId(rst.getInt("TENANT_ID")); + geofenceDataList.add(geofenceData); + } + return geofenceDataList; + } +}