RANGER-1365: Modify Ranger Hbase Plugin ColumnIterator to use Cell instead of KeyValue (to avoid ClassCastException in certain cases)

Signed-off-by: rmani <rmani@hortonworks.com>
diff --git a/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/ColumnIterator.java b/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/ColumnIterator.java
index ccccb4e..7d78c08 100644
--- a/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/ColumnIterator.java
+++ b/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/ColumnIterator.java
@@ -26,7 +26,8 @@
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.apache.hadoop.hbase.KeyValue;
+import org.apache.hadoop.hbase.Cell;
+import org.apache.hadoop.hbase.CellUtil;
 import org.apache.hadoop.hbase.util.Bytes;
 
 public class ColumnIterator implements Iterator<String> {
@@ -34,7 +35,7 @@
 	
 	private static final Log LOG = LogFactory.getLog(ColumnIterator.class.getName());
 	Iterator<byte[]> _setIterator;
-	Iterator<KeyValue> _listIterator;
+	Iterator<Cell> _listIterator;
 	
 	@SuppressWarnings("unchecked")
 	public ColumnIterator(Collection<?> columnCollection) {
@@ -42,7 +43,7 @@
 			if (columnCollection instanceof Set) {
 				_setIterator = ((Set<byte[]>)columnCollection).iterator();
 			} else if (columnCollection instanceof List) {
-				_listIterator = ((List<KeyValue>)columnCollection).iterator();
+				_listIterator = ((List<Cell>)columnCollection).iterator();
 			} else { // unexpected
 				// TODO make message better
 				LOG.error("Unexpected type " + columnCollection.getClass().getName() + " passed as value in column family collection");
@@ -73,8 +74,8 @@
 				value = Bytes.toString(valueBytes);
 			}
 		} else if (_listIterator != null) {
-			KeyValue kv = _listIterator.next();
-			byte[] v = kv.getQualifier();
+			Cell cell = _listIterator.next();
+			byte[] v = CellUtil.cloneQualifier(cell);
 			if (v != null) {
 				value = Bytes.toString(v);
 			}
diff --git a/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/RangerAuthorizationCoprocessor.java b/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/RangerAuthorizationCoprocessor.java
index 5dd727b..8ee3580 100644
--- a/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/RangerAuthorizationCoprocessor.java
+++ b/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/RangerAuthorizationCoprocessor.java
@@ -243,9 +243,15 @@
 				} else {
 					Iterator<String> columnIterator = new ColumnIterator(columnCollection);
 					Set<String> columns = new HashSet<String>();
-					while (columnIterator.hasNext()) {
-						String column = columnIterator.next();
-						columns.add(column);
+					try {
+						while (columnIterator.hasNext()) {
+							String column = columnIterator.next();
+							columns.add(column);
+						}
+					} catch (Throwable t) {
+						LOG.error("Exception encountered when converting family-map to set of columns. Ignoring and returning empty set of columns for family[" + family + "]", t);
+						LOG.error("Ignoring exception and returning empty set of columns for family[" + family +"]");
+						columns.clear();
 					}
 					result.put(family, columns);
 				}
@@ -293,8 +299,8 @@
 	}
 	
 	ColumnFamilyAccessResult evaluateAccess(String operation, Action action, final RegionCoprocessorEnvironment env,
-			final Map<byte[], ? extends Collection<?>> familyMap) throws AccessDeniedException {
-		
+											final Map<byte[], ? extends Collection<?>> familyMap) throws AccessDeniedException {
+
 		String access = _authUtils.getAccess(action);
 		User user = getActiveUser();
 		String userName = _userUtils.getUserAsString(user);
diff --git a/hbase-agent/src/test/java/org/apache/ranger/authorization/hbase/ColumnIteratorTest.java b/hbase-agent/src/test/java/org/apache/ranger/authorization/hbase/ColumnIteratorTest.java
index 4b40038..917062b 100644
--- a/hbase-agent/src/test/java/org/apache/ranger/authorization/hbase/ColumnIteratorTest.java
+++ b/hbase-agent/src/test/java/org/apache/ranger/authorization/hbase/ColumnIteratorTest.java
@@ -27,7 +27,7 @@
 import java.util.List;
 import java.util.Set;
 
-import org.apache.hadoop.hbase.KeyValue;
+import org.apache.hadoop.hbase.Cell;
 import org.junit.Assert;
 import org.junit.Test;
 import org.mockito.invocation.InvocationOnMock;
@@ -94,12 +94,12 @@
 
 	@SuppressWarnings("unchecked")
 	@Test
-	public void test_ListOfKeyValue() {
+	public void test_ListOfCell() {
 		/*
 		 * We are not interested in validating the behavior of the real iterator.  Instead just the behavior specific to the column iterator.
 		 */
 		final String[] qualifiers = new String[] {"a", "b", "c"};
-		Iterator<KeyValue> iterator = mock(Iterator.class);
+		Iterator<Cell> iterator = mock(Iterator.class);
 		// Have the iterator return true as many times as the size of keys array
 		when(iterator.hasNext()).thenAnswer(new Answer<Boolean>() {
 			int i = 0;
@@ -108,19 +108,21 @@
 				return i++ < qualifiers.length;
 			}
 		});
-		// have the iterator return a KeyValue composed of the key and value arrays
-		when(iterator.next()).thenAnswer(new Answer<KeyValue>() {
+		// have the iterator return a Cell composed of the key and value arrays
+		when(iterator.next()).thenAnswer(new Answer<Cell>() {
 			int i = 0;
 			@Override
-			public KeyValue answer(InvocationOnMock invocation)
+			public Cell answer(InvocationOnMock invocation)
 					throws Throwable {
-				KeyValue kv = mock(KeyValue.class);
-				when(kv.getQualifier()).thenReturn(qualifiers[i++].getBytes());
-				return kv;
+				Cell cell = mock(Cell.class);
+				when(cell.getQualifierOffset()).thenReturn(0);
+				when(cell.getQualifierLength()).thenReturn(1);
+				when(cell.getQualifierArray()).thenReturn(qualifiers[i++].getBytes());
+				return cell;
 			}
 		});
 		// stuff it into the collection
-		List<KeyValue> list = mock(List.class);
+		List<Cell> list = mock(List.class);
 		when(list.iterator()).thenReturn(iterator);
 		// now let's check the behavior
 		ColumnIterator columnIterator = new ColumnIterator(list);