RANGER-3846: Ranger DB patch 058 failing when multiple policies having same resourceSignature
diff --git a/security-admin/src/main/java/org/apache/ranger/biz/RangerPolicyRetriever.java b/security-admin/src/main/java/org/apache/ranger/biz/RangerPolicyRetriever.java
index 238fecd..e94c37f 100644
--- a/security-admin/src/main/java/org/apache/ranger/biz/RangerPolicyRetriever.java
+++ b/security-admin/src/main/java/org/apache/ranger/biz/RangerPolicyRetriever.java
@@ -343,7 +343,7 @@
 				ret = userScreenNames.get(userId);
 
 				if(ret == null) {
-					XXPortalUser user = daoMgr.getXXPortalUser().getById(userId);
+					XXPortalUser user = daoMgr.getXXPortalUser().findById(userId);
 
 					if(user != null) {
 						ret = user.getPublicScreenName();
diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXPolicyDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXPolicyDao.java
index 4677c37..dc58be3 100644
--- a/security-admin/src/main/java/org/apache/ranger/db/XXPolicyDao.java
+++ b/security-admin/src/main/java/org/apache/ranger/db/XXPolicyDao.java
@@ -18,7 +18,9 @@
 package org.apache.ranger.db;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import javax.persistence.NoResultException;
 
@@ -356,4 +358,34 @@
 		}
 		return ret;
 	}
+
+	public Map<String, Long> findDuplicatePoliciesByServiceAndResourceSignature() {
+		Map<String, Long> policies = new HashMap<String, Long>();
+		try {
+			List<Object[]> rows = (List<Object[]>) getEntityManager().createNamedQuery("XXPolicy.findDuplicatePoliciesByServiceAndResourceSignature").getResultList();
+			if (rows != null) {
+				for (Object[] row : rows) {
+					policies.put((String) row[0], (Long) row[1]);
+				}
+			}
+		} catch (NoResultException e) {
+			return null;
+		} catch (Exception ex) {
+		}
+		return policies;
+	}
+
+	public List<XXPolicy> findByServiceIdAndResourceSignature(Long serviceId, String policySignature) {
+		if (policySignature == null || serviceId == null) {
+			return new ArrayList<XXPolicy>();
+		}
+		try {
+			return getEntityManager().createNamedQuery("XXPolicy.findByServiceIdAndResourceSignature", tClass)
+					.setParameter("serviceId", serviceId)
+					.setParameter("resSignature", policySignature)
+					.getResultList();
+		} catch (NoResultException e) {
+			return new ArrayList<XXPolicy>();
+		}
+	}
 }
\ No newline at end of file
diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXPortalUserDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXPortalUserDao.java
index 8d15a32..1787eea 100644
--- a/security-admin/src/main/java/org/apache/ranger/db/XXPortalUserDao.java
+++ b/security-admin/src/main/java/org/apache/ranger/db/XXPortalUserDao.java
@@ -128,4 +128,25 @@
 			return null;
 		}
 	}
+
+	public XXPortalUser findById(Long id) {
+		XXPortalUser xXPortalUser = null;
+		if (id == null) {
+			return xXPortalUser;
+		}
+		try {
+			xXPortalUser = new XXPortalUser();
+			Object[] row = (Object[]) getEntityManager().createNamedQuery("XXPortalUser.findById").setParameter("id", id).getSingleResult();
+			if (row != null) {
+				xXPortalUser.setFirstName((String) row[0]);
+				xXPortalUser.setLastName((String) row[1]);
+				xXPortalUser.setPublicScreenName((String) row[2]);
+				xXPortalUser.setLoginId((String) row[3]);
+				return xXPortalUser;
+			}
+		} catch (NoResultException e) {
+			return null;
+		}
+		return xXPortalUser;
+	}
 }
diff --git a/security-admin/src/main/java/org/apache/ranger/patch/PatchPreSql_058_ForUpdateToUniqueResoureceSignature_J10053.java b/security-admin/src/main/java/org/apache/ranger/patch/PatchPreSql_058_ForUpdateToUniqueResoureceSignature_J10053.java
index 0227298..fb7e5fd 100644
--- a/security-admin/src/main/java/org/apache/ranger/patch/PatchPreSql_058_ForUpdateToUniqueResoureceSignature_J10053.java
+++ b/security-admin/src/main/java/org/apache/ranger/patch/PatchPreSql_058_ForUpdateToUniqueResoureceSignature_J10053.java
@@ -17,14 +17,18 @@
 
 package org.apache.ranger.patch;
 
+import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.ranger.authorization.utils.JsonUtils;
 import org.apache.ranger.biz.ServiceDBStore;
 import org.apache.ranger.common.RangerFactory;
 import org.apache.ranger.db.RangerDaoManager;
+import org.apache.ranger.db.XXPolicyLabelMapDao;
 import org.apache.ranger.entity.XXPolicy;
+import org.apache.ranger.entity.XXPolicyLabelMap;
 import org.apache.ranger.plugin.model.RangerPolicy;
 import org.apache.ranger.plugin.model.RangerPolicyResourceSignature;
 import org.apache.ranger.util.CLIUtil;
@@ -89,6 +93,7 @@
 
 		try {
 			updateDisabledPolicyResourceSignature();
+			removeDuplicateResourceSignaturesPolicies();
 		} catch (Exception e) {
 			logger.error("Error while PatchPreSql_058_ForUpdateToUniqueResoureceSignature_J10053()", e);
 			System.exit(1);
@@ -128,4 +133,49 @@
 		}
 	}
 
+	private void removeDuplicateResourceSignaturesPolicies() throws Exception {
+		logger.info("==> removeDuplicateResourceSignaturesPolicies() ");
+		Map<String, Long> duplicateEntries = daoMgr.getXXPolicy().findDuplicatePoliciesByServiceAndResourceSignature();
+		if (duplicateEntries != null && duplicateEntries.size() > 0) {
+			logger.info("Total number of possible duplicate policies:" + duplicateEntries.size());
+			for (Map.Entry<String, Long> entry : duplicateEntries.entrySet()) {
+				logger.info("Duplicate policy Entry - {ResourceSignature:" + entry.getKey() + ", ServiceId:" + entry.getValue() + "}");
+				List<XXPolicy> xxPolicyList = daoMgr.getXXPolicy().findByServiceIdAndResourceSignature(entry.getValue(), entry.getKey());
+				if (CollectionUtils.isNotEmpty(xxPolicyList) && xxPolicyList.size() > 1) {
+					Iterator<XXPolicy> duplicatePolicies = xxPolicyList.iterator();
+					duplicatePolicies.next();
+					while (duplicatePolicies.hasNext()) {
+						XXPolicy xxPolicy = duplicatePolicies.next();
+						if (xxPolicy != null) {
+							logger.info("Attempting to Remove duplicate policy:{" + xxPolicy.getId() + ":" + xxPolicy.getName() + "}");
+							if (cleanupRefTables(xxPolicy.getId())) {
+								daoMgr.getXXPolicy().remove(xxPolicy.getId());
+							}
+						}
+					}
+				}
+			}
+		} else {
+			logger.info("no duplicate Policy found");
+		}
+	}
+
+	private Boolean cleanupRefTables(Long policyId) {
+		if (policyId == null) {
+			return false;
+		}
+		daoMgr.getXXPolicyRefResource().deleteByPolicyId(policyId);
+		daoMgr.getXXPolicyRefRole().deleteByPolicyId(policyId);
+		daoMgr.getXXPolicyRefGroup().deleteByPolicyId(policyId);
+		daoMgr.getXXPolicyRefUser().deleteByPolicyId(policyId);
+		daoMgr.getXXPolicyRefAccessType().deleteByPolicyId(policyId);
+		daoMgr.getXXPolicyRefCondition().deleteByPolicyId(policyId);
+		daoMgr.getXXPolicyRefDataMaskType().deleteByPolicyId(policyId);
+		XXPolicyLabelMapDao policyLabelMapDao = daoMgr.getXXPolicyLabelMap();
+		List<XXPolicyLabelMap> xxPolicyLabelMaps = policyLabelMapDao.findByPolicyId(policyId);
+		for (XXPolicyLabelMap xxPolicyLabelMap : xxPolicyLabelMaps) {
+			policyLabelMapDao.remove(xxPolicyLabelMap);
+		}
+		return true;
+	}
 }
diff --git a/security-admin/src/main/resources/META-INF/jpa_named_queries.xml b/security-admin/src/main/resources/META-INF/jpa_named_queries.xml
index 7e69cc4..e4a2354 100755
--- a/security-admin/src/main/resources/META-INF/jpa_named_queries.xml
+++ b/security-admin/src/main/resources/META-INF/jpa_named_queries.xml
@@ -418,6 +418,14 @@
 		<query>select obj from XXPolicy obj, XXService svc, XXSecurityZone zone where obj.guid = :guid and obj.service = svc.id and svc.name = :serviceName and obj.zoneId = zone.id and zone.name = :zoneName</query>
 	</named-query>
 
+	<named-query name="XXPolicy.findDuplicatePoliciesByServiceAndResourceSignature">
+		<query>select obj.resourceSignature, obj.service from XXPolicy obj GROUP BY obj.resourceSignature, obj.service HAVING COUNT(obj.resourceSignature) > 1</query>
+	</named-query>
+
+	<named-query name="XXPolicy.findByServiceIdAndResourceSignature">
+		<query>select obj from XXPolicy obj where obj.service = :serviceId and obj.resourceSignature = :resSignature</query>
+	</named-query>
+
 	<!-- XXServiceDef -->
 	<named-query name="XXServiceDef.findByName">
 		<query>select obj from XXServiceDef obj where obj.name = :name</query>
@@ -1192,6 +1200,10 @@
 		<query>SELECT obj FROM XXPortalUser obj WHERE obj.userSource=:userSource and obj.status=:status</query>
 	</named-query>
 
+	<named-query name="XXPortalUser.findById">
+		<query>SELECT obj.firstName, obj.lastName, obj.publicScreenName, obj.loginId FROM XXPortalUser obj WHERE obj.id=:id</query>
+	</named-query>
+
 	<!-- VXModuleDef -->
 	<named-query name="XXModuleDef.findByModuleId">
 		<query>SELECT obj FROM XXModuleDef obj