You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ranger.apache.org by ma...@apache.org on 2015/03/14 19:52:25 UTC

[1/4] incubator-ranger git commit: RANGER-278 move validation classes under org.apache.ranger.plugin.model.validation

Repository: incubator-ranger
Updated Branches:
  refs/heads/master 9b3597617 -> 7bb686873


http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/security-admin/src/test/java/org/apache/ranger/rest/TestRangerPolicyValidator.java
----------------------------------------------------------------------
diff --git a/security-admin/src/test/java/org/apache/ranger/rest/TestRangerPolicyValidator.java b/security-admin/src/test/java/org/apache/ranger/rest/TestRangerPolicyValidator.java
deleted file mode 100644
index 2fb82ce..0000000
--- a/security-admin/src/test/java/org/apache/ranger/rest/TestRangerPolicyValidator.java
+++ /dev/null
@@ -1,524 +0,0 @@
-package org.apache.ranger.rest;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.ranger.plugin.model.RangerPolicy;
-import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItem;
-import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemAccess;
-import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
-import org.apache.ranger.plugin.model.RangerService;
-import org.apache.ranger.plugin.model.RangerServiceDef;
-import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
-import org.apache.ranger.plugin.store.ServiceStore;
-import org.apache.ranger.plugin.util.SearchFilter;
-import org.apache.ranger.rest.RangerPolicyValidator;
-import org.apache.ranger.rest.ValidationFailureDetails;
-import org.apache.ranger.rest.RangerValidator.Action;
-import org.junit.Before;
-import org.junit.Test;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Sets;
-
-public class TestRangerPolicyValidator {
-
-	@Before
-	public void setUp() throws Exception {
-		_store = mock(ServiceStore.class);
-		_policy = mock(RangerPolicy.class);
-		_validator = new RangerPolicyValidator(_store);
-		_serviceDef = mock(RangerServiceDef.class);
-	}
-	
-	final Action[] cu = new Action[] { Action.CREATE, Action.UPDATE };
-	final Object[] policyItemsData = new Object[] {
-			ImmutableMap.of(  // all good
-				"users", new String[] {"user1" ," user2"},
-				"groups", new String[] {"group1", "group2"},
-				"accesses", new String[] { "r", "w" },
-				"isAllowed", new Boolean[] { true, true }),
-			ImmutableMap.of(   // no users, access type different case
-				"groups", new String[] {"group3", "group4"},
-				"accesses", new String[]{"W", "x"}, 
-				"isAllowed", new Boolean[] { true, true }),
-			ImmutableMap.of(   // no groups
-				"users", new String[] {"user3" ," user4"}, 
-				"accesses", new String[] { "r", "x" },
-				"isAllowed", new Boolean[] { true, true }),
-			ImmutableMap.of( // isallowed on access types is null, case is different from that in definition
-				"users", new String[] {"user7" ," user6"},
-				"accesses", new String[] { "a" },
-				"isAllowed", new Boolean[] { null, null })
-	};
-	String[] accessTypes = new String[] { "r", "w", "x", "A" };  // mix of lower and upper case
-	String[] accessTypes_bad = new String[] { "r", "w", "xx", }; // two missing (x, a), one new that isn't on bad (xx)
-	
-	private final Object[][] resourceDefData = new Object[][] {
-			// { name, mandatory, reg-exp, excludesSupported, recursiveSupported }
-			{ "db", true, "db\\d+", null, null }, // valid values: db1, db22, db983, etc.; invalid: db, db12x, ttx11, etc.; null => false for excludes and recursive
-			{ "tbl", true, null, true, true }, // regex == null => anything goes; excludes == true, recursive == true
-			{ "col", false, "col\\d{1,2}", false, true }  // valid: col1, col47, etc.; invalid: col, col238, col1, etc., excludes == false, recursive == true 
-	};
-	
-	private final Object[][] policyResourceMap_good = new Object[][] {
-			// resource-name, values, excludes, recursive
-			{ "db", new String[] { "db1", "db2" }, null, null },
-			{ "TBL", new String[] { "tbl1", "tbl2" }, true, false } // case should not matter
-	};
-	
-	private final Object[][] policyResourceMap_bad = new Object[][] {
-			// resource-name, values, excludes, recursive
-			{ "db", new String[] { "db1", "db2" }, null, true },        // mandatory "tbl" missing; recursive==true specified when resource-def does not support it (null) 
-			{"col", new String[] { "col12", "col 1" }, true, true },    // wrong format of value for "col"; excludes==true specified when resource-def does not allow it (false)
-			{"extra", new String[] { "extra1", "extra2" }, null, null } // spurious "extra" specified
-	};
-
-	@Test
-	public final void testIsValid_long() throws Exception {
-		// this validation should be removed if we start supporting other than delete action
-		assertFalse(_validator.isValid(3L, Action.CREATE, _failures));
-		_utils.checkFailureForInternalError(_failures);
-		
-		// should fail with appropriate error message if id is null
-		_failures.clear(); _failures.clear(); assertFalse(_validator.isValid((Long)null, Action.DELETE, _failures));
-		_utils.checkFailureForMissingValue(_failures, "id");
-		
-		// should fail with appropriate error message if policy can't be found for the specified id
-		when(_store.getPolicy(1L)).thenReturn(null);
-		when(_store.getPolicy(2L)).thenThrow(new Exception());
-		RangerPolicy existingPolicy = mock(RangerPolicy.class);
-		when(_store.getPolicy(3L)).thenReturn(existingPolicy);
-		_failures.clear(); assertFalse(_validator.isValid(1L, Action.DELETE, _failures));
-		_utils.checkFailureForSemanticError(_failures, "id");
-		_failures.clear(); assertFalse(_validator.isValid(2L, Action.DELETE, _failures));
-		_utils.checkFailureForSemanticError(_failures, "id");
-
-		// if policy exists then delete validation should pass 
-		assertTrue(_validator.isValid(3L, Action.DELETE, _failures));
-	}
-	
-	@Test
-	public final void testIsValid_happyPath() throws Exception {
-		// valid policy has valid non-empty name and service name 
-		when(_policy.getService()).thenReturn("service-name");
-		// service name exists
-		RangerService service = mock(RangerService.class);
-		when(service.getType()).thenReturn("service-type");
-		when(_store.getServiceByName("service-name")).thenReturn(service);
-		// service points to a valid service-def
-		_serviceDef = _utils.createServiceDefWithAccessTypes(accessTypes);
-		when(_store.getServiceDefByName("service-type")).thenReturn(_serviceDef);
-		// a matching policy should exist for create when checked by id and not exist when checked by name.
-		when(_store.getPolicy(7L)).thenReturn(null);
-		RangerPolicy existingPolicy = mock(RangerPolicy.class);
-		when(existingPolicy.getId()).thenReturn(8L);
-		when(_store.getPolicy(8L)).thenReturn(existingPolicy);
-		SearchFilter createFilter = new SearchFilter();
-		createFilter.setParam(SearchFilter.POLICY_NAME, "service-type");
-		createFilter.setParam(SearchFilter.POLICY_NAME, "policy-name-1"); // this name would be used for create
-		when(_store.getPolicies(createFilter)).thenReturn(new ArrayList<RangerPolicy>());
-		// a matching policy should not exist for update.
-		SearchFilter updateFilter = new SearchFilter();
-		updateFilter.setParam(SearchFilter.POLICY_NAME, "service-type");
-		updateFilter.setParam(SearchFilter.POLICY_NAME, "policy-name-2"); // this name would be used for update
-		List<RangerPolicy> existingPolicies = new ArrayList<RangerPolicy>();
-		existingPolicies.add(existingPolicy);
-		when(_store.getPolicies(updateFilter)).thenReturn(existingPolicies);
-		// valid policy can have empty set of policy items if audit is turned on
-		// null value for audit is treated as audit on.
-		for (Action action : cu) {
-			for (Boolean auditEnabled : new Boolean[] { null, true } ) {
-				when(_policy.getIsAuditEnabled()).thenReturn(auditEnabled);
-				if (action == Action.CREATE) {
-					when(_policy.getId()).thenReturn(7L);
-					when(_policy.getName()).thenReturn("policy-name-1");
-					assertTrue("" + action + ", " + auditEnabled, _validator.isValid(_policy, action, _failures));
-					assertTrue(_failures.isEmpty());
-				} else {
-					// update should work both when by-name is found or not, since nothing found by-name means name is being updated.
-					when(_policy.getId()).thenReturn(8L);
-					when(_policy.getName()).thenReturn("policy-name-1");
-					assertTrue("" + action + ", " + auditEnabled, _validator.isValid(_policy, action, _failures));
-					assertTrue(_failures.isEmpty());
-
-					when(_policy.getName()).thenReturn("policy-name-2");
-					assertTrue("" + action + ", " + auditEnabled, _validator.isValid(_policy, action, _failures));
-					assertTrue(_failures.isEmpty());
-				}
-			}
-		}
-		// if audit is disabled then policy should have policy items and all of them should be valid
-		List<RangerPolicyItem> policyItems = _utils.createPolicyItems(policyItemsData);
-		when(_policy.getPolicyItems()).thenReturn(policyItems);
-		when(_policy.getIsAuditEnabled()).thenReturn(false);
-		for (Action action : cu) {
-			if (action == Action.CREATE) {
-				when(_policy.getId()).thenReturn(7L);
-				when(_policy.getName()).thenReturn("policy-name-1");
-			} else {
-				when(_policy.getId()).thenReturn(8L);
-				when(_policy.getName()).thenReturn("policy-name-2");
-			}
-			assertTrue("" + action , _validator.isValid(_policy, action, _failures));
-			assertTrue(_failures.isEmpty());
-		}
-		
-		// above succeeded as service def did not have any resources on it, mandatory or otherwise.
-		// policy should have all mandatory resources specified, and they should conform to the validation pattern in resource definition
-		List<RangerResourceDef> resourceDefs = _utils.createResourceDefs(resourceDefData);
-		when(_serviceDef.getResources()).thenReturn(resourceDefs);
-		Map<String, RangerPolicyResource> resourceMap = _utils.createPolicyResourceMap(policyResourceMap_good);
-		when(_policy.getResources()).thenReturn(resourceMap);
-
-		for (Action action : cu) {
-			if (action == Action.CREATE) {
-				when(_policy.getId()).thenReturn(7L);
-				when(_policy.getName()).thenReturn("policy-name-1");
-			} else {
-				when(_policy.getId()).thenReturn(8L);
-				when(_policy.getName()).thenReturn("policy-name-2");
-			}
-			assertTrue("" + action , _validator.isValid(_policy, action, _failures));
-			assertTrue(_failures.isEmpty());
-		}
-	}
-	
-	void checkFailure_isValid(Action action, String errorType, String field) {
-		checkFailure_isValid(action, errorType, field, null);
-	}
-	
-	void checkFailure_isValid(Action action, String errorType, String field, String subField) {
-		_failures.clear();
-		assertFalse(_validator.isValid(_policy, action, _failures));
-		switch (errorType) {
-		case "missing":
-			_utils.checkFailureForMissingValue(_failures, field, subField);
-			break;
-		case "semantic":
-			_utils.checkFailureForSemanticError(_failures, field, subField);
-			break;
-		case "internal error":
-			_utils.checkFailureForInternalError(_failures);
-			break;
-		default:
-			fail("Unsupported errorType[" + errorType + "]");
-			break;
-		}
-	}
-	
-	@Test
-	public final void testIsValid_failures() throws Exception {
-		for (Action action : cu) {
-			// passing in a null policy should fail with appropriate failure reason
-			_policy = null;
-			checkFailure_isValid(action, "missing", "policy");
-			
-			// policy must have a name on it
-			_policy = mock(RangerPolicy.class);
-			for (String name : new String[] { null, "  " }) {
-				when(_policy.getName()).thenReturn(name);
-				checkFailure_isValid(action, "missing", "name");
-			}
-			
-			// for update id is required!
-			if (action == Action.UPDATE) {
-				when(_policy.getId()).thenReturn(null);
-				checkFailure_isValid(action, "missing", "id");
-			}
-		}
-		/*
-		 * Id is ignored for Create but name should not belong to an existing policy.  For update, policy should exist for its id and should match its name.
-		 */
-		when(_policy.getName()).thenReturn("policy-name");
-		when(_policy.getService()).thenReturn("service-name");
-
-		RangerPolicy existingPolicy = mock(RangerPolicy.class);
-		when(existingPolicy.getId()).thenReturn(7L);
-		List<RangerPolicy> existingPolicies = new ArrayList<RangerPolicy>();
-		existingPolicies.add(existingPolicy);
-		SearchFilter filter = new SearchFilter();
-		filter.setParam(SearchFilter.SERVICE_NAME, "service-name");
-		filter.setParam(SearchFilter.POLICY_NAME, "policy-name");
-		when(_store.getPolicies(filter)).thenReturn(existingPolicies);
-		checkFailure_isValid(Action.CREATE, "semantic", "name");
-		
-		// update : does not exist for id
-		when(_policy.getId()).thenReturn(7L);
-		when(_store.getPolicy(7L)).thenReturn(null);
-		checkFailure_isValid(Action.UPDATE, "semantic", "id");
-
-		// Update: name should not point to an existing different policy, i.e. with a different id
-		when(_store.getPolicy(7L)).thenReturn(existingPolicy);
-		RangerPolicy anotherExistingPolicy = mock(RangerPolicy.class);
-		when(anotherExistingPolicy.getId()).thenReturn(8L);
-		existingPolicies.clear();
-		existingPolicies.add(anotherExistingPolicy);
-		when(_store.getPolicies(filter)).thenReturn(existingPolicies);
-		checkFailure_isValid(Action.UPDATE, "semantic", "id/name");
-
-		// more than one policies with same name is also an internal error
-		when(_policy.getName()).thenReturn("policy-name");
-		when(_store.getPolicies(filter)).thenReturn(existingPolicies);
-		existingPolicies.add(existingPolicy);
-		existingPolicy = mock(RangerPolicy.class);
-		existingPolicies.add(existingPolicy);
-		_failures.clear(); assertFalse(_validator.isValid(_policy, Action.UPDATE, _failures));
-		_utils.checkFailureForInternalError(_failures);
-		
-		// policy must have service name on it and it should be valid
-		when(_policy.getName()).thenReturn("policy-name");
-		when(_store.getServiceByName("service-name")).thenReturn(null);
-		when(_store.getServiceByName("another-service-name")).thenThrow(new Exception());
-
-		for (Action action : cu) {
-			when(_policy.getService()).thenReturn("service-name");
-			_failures.clear(); assertFalse(_validator.isValid(_policy, action, _failures));
-			_utils.checkFailureForMissingValue(_failures, "service");
-
-			when(_policy.getService()).thenReturn("another-service-name");
-			_failures.clear(); assertFalse(_validator.isValid(_policy, action, _failures));
-			_utils.checkFailureForMissingValue(_failures, "service");
-		}
-		
-		// policy must contain at least one policy item
-		List<RangerPolicyItem> policyItems = new ArrayList<RangerPolicy.RangerPolicyItem>();
-		when(_policy.getService()).thenReturn("service-name");
-		RangerService service = mock(RangerService.class);
-		when(_store.getServiceByName("service-name")).thenReturn(service);
-		for (Action action : cu) {
-			// when it is null
-			when(_policy.getPolicyItems()).thenReturn(null);
-			_failures.clear(); assertFalse(_validator.isValid(_policy, action, _failures));
-			_utils.checkFailureForMissingValue(_failures, "policy items");
-			// or when it is not null but empty.
-			when(_policy.getPolicyItems()).thenReturn(policyItems);
-			_failures.clear(); assertFalse(_validator.isValid(_policy, action, _failures));
-			_utils.checkFailureForMissingValue(_failures, "policy items");
-		}
-		
-		// these are known good policy items -- same as used above in happypath
-		policyItems = _utils.createPolicyItems(policyItemsData);
-		when(_policy.getPolicyItems()).thenReturn(policyItems);
-		// policy item check requires that service def should exist
-		when(service.getType()).thenReturn("service-type");
-		when(_store.getServiceDefByName("service-type")).thenReturn(null);
-		for (Action action : cu) {
-			_failures.clear(); assertFalse(_validator.isValid(_policy, action, _failures));
-			_utils.checkFailureForInternalError(_failures, "policy service def");
-		}
-		
-		// service-def should contain the right access types on it.
-		_serviceDef = _utils.createServiceDefWithAccessTypes(accessTypes_bad);
-		when(_store.getServiceDefByName("service-type")).thenReturn(_serviceDef);
-		for (Action action : cu) {
-			_failures.clear(); assertFalse(_validator.isValid(_policy, action, _failures));
-			_utils.checkFailureForSemanticError(_failures, "policy item access type");
-		}
-
-		// create the right service def with right resource defs - this is the same as in the happypath test above.
-		_serviceDef = _utils.createServiceDefWithAccessTypes(accessTypes);
-		when(_store.getPolicies(filter)).thenReturn(null);
-		List<RangerResourceDef> resourceDefs = _utils.createResourceDefs(resourceDefData);
-		when(_serviceDef.getResources()).thenReturn(resourceDefs);
-		when(_store.getServiceDefByName("service-type")).thenReturn(_serviceDef);
-		// one mandtory is missing (tbl) and one unknown resource is specified (extra), and values of option resource don't conform to validation pattern (col)
-		Map<String, RangerPolicyResource> policyResources = _utils.createPolicyResourceMap(policyResourceMap_bad);
-		when(_policy.getResources()).thenReturn(policyResources);
-		for (Action action : cu) {
-			_failures.clear(); assertFalse(_validator.isValid(_policy, action, _failures));
-			_utils.checkFailureForMissingValue(_failures, "resources", "tbl"); // for missing resource: tbl
-			_utils.checkFailureForSemanticError(_failures, "resources", "extra"); // for spurious resource: "extra"
-			_utils.checkFailureForSemanticError(_failures, "resource-values", "col"); // for spurious resource: "extra"
-			_utils.checkFailureForSemanticError(_failures, "isRecursive", "db"); // for specifying it as true when def did not allow it
-			_utils.checkFailureForSemanticError(_failures, "isExcludes", "col"); // for specifying it as true when def did not allow it
-		}
-	}
-	
-	@Test
-	public void test_isValidResourceValues() {
-		List<RangerResourceDef> resourceDefs = _utils.createResourceDefs(resourceDefData);
-		when(_serviceDef.getResources()).thenReturn(resourceDefs);
-		Map<String, RangerPolicyResource> policyResources = _utils.createPolicyResourceMap(policyResourceMap_bad);
-		assertFalse(_validator.isValidResourceValues(policyResources, _failures, _serviceDef));
-		_utils.checkFailureForSemanticError(_failures, "resource-values", "col");
-		
-		policyResources = _utils.createPolicyResourceMap(policyResourceMap_good);
-		assertTrue(_validator.isValidResourceValues(policyResources, _failures, _serviceDef));
-	}
-	
-	@Test
-	public void test_isValidPolicyItems_failures() {
-		// null/empty list is good because there is nothing
-		assertTrue(_validator.isValidPolicyItems(null, _failures, _serviceDef));
-		_failures.isEmpty();
-
-		List<RangerPolicyItem> policyItems = new ArrayList<RangerPolicy.RangerPolicyItem>();
-		assertTrue(_validator.isValidPolicyItems(policyItems, _failures, _serviceDef));
-		_failures.isEmpty();
-		
-		// null elements in the list are flagged
-		policyItems.add(null);
-		assertFalse(_validator.isValidPolicyItems(policyItems, _failures, _serviceDef));
-		_utils.checkFailureForMissingValue(_failures, "policy item");
-	}
-	
-	@Test
-	public void test_isValidPolicyItem_failures() {
-
-		// empty access collections are invalid
-		RangerPolicyItem policyItem = mock(RangerPolicyItem.class);
-		when(policyItem.getAccesses()).thenReturn(null);
-		_failures.clear(); assertFalse(_validator.isValidPolicyItem(policyItem, _failures, _serviceDef));
-		_utils.checkFailureForMissingValue(_failures, "policy item accesses");
-
-		List<RangerPolicyItemAccess> accesses = new ArrayList<RangerPolicy.RangerPolicyItemAccess>();
-		when(policyItem.getAccesses()).thenReturn(accesses);
-		_failures.clear(); assertFalse(_validator.isValidPolicyItem(policyItem, _failures, _serviceDef));
-		_utils.checkFailureForMissingValue(_failures, "policy item accesses");
-		
-		// both user and groups can't be null
-		RangerPolicyItemAccess access = mock(RangerPolicyItemAccess.class);
-		accesses.add(access);
-		when(policyItem.getUsers()).thenReturn(null);
-		when(policyItem.getGroups()).thenReturn(new ArrayList<String>());
-		_failures.clear(); assertFalse(_validator.isValidPolicyItem(policyItem, _failures, _serviceDef));
-		_utils.checkFailureForMissingValue(_failures, "policy item users/user-groups");
-	}
-	
-	@Test
-	public void test_isValidItemAccesses_happyPath() {
-		
-		// happy path
-		Object[][] data = new Object[][] {
-				{ "a", null }, // valid
-				{ "b", true }, // valid
-				{ "c", true }, // valid
-		};
-		List<RangerPolicyItemAccess> accesses = _utils.createItemAccess(data);
-		_serviceDef = _utils.createServiceDefWithAccessTypes(new String[] { "a", "b", "c", "d" });
-		assertTrue(_validator.isValidItemAccesses(accesses, _failures, _serviceDef));
-		assertTrue(_failures.isEmpty());
-	}
-	
-	@Test
-	public void test_isValidItemAccesses_failure() {
-
-		// null policy item access values are an error
-		List<RangerPolicyItemAccess> accesses = new ArrayList<RangerPolicyItemAccess>();
-		accesses.add(null);
-		_failures.clear(); assertFalse(_validator.isValidItemAccesses(accesses, _failures, _serviceDef));
-		_utils.checkFailureForMissingValue(_failures, "policy item access");
-
-		// all items must be valid for this call to be valid
-		Object[][] data = new Object[][] {
-				{ "a", null }, // valid
-				{ null, null }, // invalid - name can't be null
-				{ "c", true }, // valid
-		};
-		accesses = _utils.createItemAccess(data);
-		_serviceDef = _utils.createServiceDefWithAccessTypes(new String[] { "a", "b", "c", "d" });
-		_failures.clear(); assertFalse(_validator.isValidItemAccesses(accesses, _failures, _serviceDef));
-	}
-	
-	@Test
-	public void test_isValidPolicyItemAccess_happyPath() {
-		
-		RangerPolicyItemAccess access = mock(RangerPolicyItemAccess.class);
-		when(access.getType()).thenReturn("an-Access"); // valid
-
-		Set<String> validAccesses = Sets.newHashSet(new String[] { "an-access", "another-access" });  // valid accesses should be lower-cased
-		
-		// both null or true access types are the same and valid
-		for (Boolean allowed : new Boolean[] { null, true } ) {
-			when(access.getIsAllowed()).thenReturn(allowed);
-			assertTrue(_validator.isValidPolicyItemAccess(access, _failures, validAccesses));
-			assertTrue(_failures.isEmpty());
-		}
-	}
-	
-	@Test
-	public void test_isValidPolicyItemAccess_failures() {
-		
-		Set<String> validAccesses = Sets.newHashSet(new String[] { "anAccess", "anotherAccess" });
-		// null/empty names are invalid
-		RangerPolicyItemAccess access = mock(RangerPolicyItemAccess.class);
-		when(access.getIsAllowed()).thenReturn(null); // valid since null == true
-		for (String type : new String[] { null, " 	"}) {
-			when(access.getType()).thenReturn(type); // invalid
-			// null/empty validAccess set skips all checks
-			assertTrue(_validator.isValidPolicyItemAccess(access, _failures, null));
-			assertTrue(_validator.isValidPolicyItemAccess(access, _failures, new HashSet<String>()));
-			_failures.clear(); assertFalse(_validator.isValidPolicyItemAccess(access, _failures, validAccesses));
-			_utils.checkFailureForMissingValue(_failures, "policy item access type");
-		}
-		
-		when(access.getType()).thenReturn("anAccess"); // valid
-		when(access.getIsAllowed()).thenReturn(false); // invalid
-		_failures.clear();assertFalse(_validator.isValidPolicyItemAccess(access, _failures, validAccesses));
-		_utils.checkFailureForSemanticError(_failures, "policy item access type allowed");
-		
-		when(access.getType()).thenReturn("newAccessType"); // invalid
-		_failures.clear(); assertFalse(_validator.isValidPolicyItemAccess(access, _failures, validAccesses));
-		_utils.checkFailureForSemanticError(_failures, "policy item access type");
-	}
-	
-	final Object[][] resourceDef_happyPath = new Object[][] {
-			// { "resource-name", "isExcludes", "isRecursive" }
-			{ "db", true, true },
-			{ "tbl", null, true },
-			{ "col", true, false },
-	};
-	
-	private Object[][] policyResourceMap_happyPath = new Object[][] {
-			// { "resource-name", "isExcludes", "isRecursive" }
-			{ "db", null, true },    // null should be treated as false
-			{ "tbl", false, false }, // set to false where def is null and def is true  
-			{ "col", true, null}     // set to null where def is false
-	};
-	
-	@Test
-	public final void test_isValidResourceFlags_happyPath() {
-		// passing null values effectively bypasses the filter
-		assertTrue(_validator.isValidResourceFlags(null, _failures, null, "a-service-def", "a-policy"));
-		// so does passing in empty collections
-		Map<String, RangerPolicyResource> resourceMap = _utils.createPolicyResourceMap2(policyResourceMap_happyPath);
-		List<RangerResourceDef> resourceDefs = _utils.createResourceDefs2(resourceDef_happyPath);
-		when(_serviceDef.getResources()).thenReturn(resourceDefs);
-		assertTrue(_validator.isValidResourceFlags(resourceMap, _failures, resourceDefs, "a-service-def", "a-policy"));
-	}
-
-	private Object[][] policyResourceMap_failures = new Object[][] {
-			// { "resource-name", "isExcludes", "isRecursive" }
-			{ "db", true, true },    // ok: def has true for both  
-			{ "tbl", true, null },   // excludes: def==false, policy==true  
-			{ "col", false, true }    // recursive: def==null (i.e. false), policy==true
-	};
-	
-	@Test
-	public final void test_isValidResourceFlags_failures() {
-		// passing true when def says false/null
-		List<RangerResourceDef> resourceDefs = _utils.createResourceDefs2(resourceDef_happyPath);
-		Map<String, RangerPolicyResource> resourceMap = _utils.createPolicyResourceMap2(policyResourceMap_failures);
-		when(_serviceDef.getResources()).thenReturn(resourceDefs);
-		assertFalse(_validator.isValidResourceFlags(resourceMap, _failures, resourceDefs, "a-service-def", "a-policy"));
-		_utils.checkFailureForSemanticError(_failures, "isExcludes", "tbl");
-		_utils.checkFailureForSemanticError(_failures, "isRecursive", "col");
-	}
-
-	private ValidationTestUtils _utils = new ValidationTestUtils();
-	private List<ValidationFailureDetails> _failures = new ArrayList<ValidationFailureDetails>();
-	private ServiceStore _store;
-	private RangerPolicy _policy;
-	private RangerPolicyValidator _validator;
-	private RangerServiceDef _serviceDef;
-}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/security-admin/src/test/java/org/apache/ranger/rest/TestRangerServiceDefValidator.java
----------------------------------------------------------------------
diff --git a/security-admin/src/test/java/org/apache/ranger/rest/TestRangerServiceDefValidator.java b/security-admin/src/test/java/org/apache/ranger/rest/TestRangerServiceDefValidator.java
deleted file mode 100644
index 8702509..0000000
--- a/security-admin/src/test/java/org/apache/ranger/rest/TestRangerServiceDefValidator.java
+++ /dev/null
@@ -1,355 +0,0 @@
-package org.apache.ranger.rest;
-
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.ranger.plugin.model.RangerServiceDef;
-import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef;
-import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumDef;
-import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumElementDef;
-import org.apache.ranger.plugin.store.ServiceStore;
-import org.apache.ranger.rest.RangerServiceDefValidator;
-import org.apache.ranger.rest.ValidationFailureDetails;
-import org.apache.ranger.rest.RangerValidator.Action;
-import org.junit.Before;
-import org.junit.Test;
-
-import com.google.common.collect.ImmutableMap;
-
-public class TestRangerServiceDefValidator {
-
-	@Before
-	public void setUp() throws Exception {
-		_store = mock(ServiceStore.class);
-		_validator = new RangerServiceDefValidator(_store);
-		_failures = new ArrayList<ValidationFailureDetails>();
-		_serviceDef = mock(RangerServiceDef.class);
-	}
-
-	final Action[] cu = new Action[] { Action.CREATE, Action.UPDATE };
-	
-	final Object[][] accessTypes_good = new Object[][] {
-			{ "read",  null },                                // ok, null implied grants
-			{ "write", new String[] {   } },                  // ok, empty implied grants
-			{ "admin", new String[] { "READ",  "write" } }    // ok, admin access implies read/write, access types are case-insensitive
-	};
-
-	final Map<String, String[]> enums_good = ImmutableMap.of(
-			"authentication-type", new String[] { "simple", "kerberos" },
-			"time-unit", new String[] { "day", "hour", "minute" }
-	);
-	
-	@Test
-	public final void test_isValid_happyPath_create() throws Exception {
-		
-		// setup access types with implied access and couple of enums
-		List<RangerAccessTypeDef> accessTypeDefs = _utils.createAccessTypeDefs(accessTypes_good);
-		when(_serviceDef.getAccessTypes()).thenReturn(accessTypeDefs);
-		List<RangerEnumDef> enumDefs = _utils.createEnumDefs(enums_good);
-		when(_serviceDef.getEnums()).thenReturn(enumDefs);
-
-		// create: id is not relevant, name should not conflict 
-		when(_serviceDef.getId()).thenReturn(null); // id is not relevant for create
-		when(_serviceDef.getName()).thenReturn("aServiceDef"); // service has a name
-		when(_store.getServiceDefByName("aServiceDef")).thenReturn(null); // no name collision
-		assertTrue(_validator.isValid(_serviceDef, Action.CREATE, _failures));
-		assertTrue(_failures.isEmpty());
-		
-		// update: id should match existing service, name should not point to different service def
-		when(_serviceDef.getId()).thenReturn(5L);
-		RangerServiceDef existingServiceDef = mock(RangerServiceDef.class);
-		when(_store.getServiceDef(5L)).thenReturn(existingServiceDef);
-		assertTrue(_validator.isValid(_serviceDef, Action.UPDATE, _failures));
-		assertTrue(_failures.isEmpty());
-		
-		// update: if name points to a service that it's id should be the same
-		RangerServiceDef anotherExistingServiceDef = mock(RangerServiceDef.class);
-		when(anotherExistingServiceDef.getId()).thenReturn(5L);
-		when(_store.getServiceDefByName("aServiceDef")).thenReturn(anotherExistingServiceDef);
-		assertTrue(_validator.isValid(_serviceDef, Action.UPDATE, _failures));
-		assertTrue(_failures.isEmpty());
-	}
-	
-	@Test
-	public final void testIsValid_Long_failures() throws Exception {
-		Long id = null;
-		// passing in wrong action type 
-		boolean result = _validator.isValid((Long)null, Action.CREATE, _failures);
-		assertFalse(result);
-		_utils.checkFailureForInternalError(_failures);
-		// passing in null id is an error
-		_failures.clear(); assertFalse(_validator.isValid((Long)null, Action.DELETE, _failures));
-		_utils.checkFailureForMissingValue(_failures, "id");
-		// a service def with that id should exist, else it is an error
-		id = 3L;
-		when(_store.getServiceDef(id)).thenReturn(null);
-		_failures.clear(); assertFalse(_validator.isValid(id, Action.DELETE, _failures));
-		_utils.checkFailureForSemanticError(_failures, "id");
-		// happypath
-		when(_store.getServiceDef(id)).thenReturn(_serviceDef);
-		_failures.clear(); assertTrue(_validator.isValid(id, Action.DELETE, _failures));
-		assertTrue(_failures.isEmpty());
-	}
-
-	@Test
-	public final void testIsValid_failures_name() throws Exception {
-		// null service def and bad service def name
-		for (Action action : cu) {
-			// passing in null service def is an error
-			assertFalse(_validator.isValid((RangerServiceDef)null, action, _failures));
-			_utils.checkFailureForMissingValue(_failures, "service def");
-			// name should be valid
-			for (String name : new String[] { null, "", "  " }) {
-				when(_serviceDef.getName()).thenReturn(name);
-				_failures.clear(); assertFalse(_validator.isValid(_serviceDef, action, _failures));
-				_utils.checkFailureForMissingValue(_failures, "name");
-			}
-		}
-	}
-	
-	@Test
-	public final void testIsValid_failures_id() throws Exception {
-		// id is required for update
-		when(_serviceDef.getId()).thenReturn(null);
-		assertFalse(_validator.isValid(_serviceDef, Action.UPDATE, _failures));
-		_utils.checkFailureForMissingValue(_failures, "id");
-		
-		// update: service should exist for the passed in id
-		Long id = 7L;
-		when(_serviceDef.getId()).thenReturn(id);
-		when(_store.getServiceDef(id)).thenReturn(null);
-		assertFalse(_validator.isValid(_serviceDef, Action.UPDATE, _failures));
-		_utils.checkFailureForSemanticError(_failures, "id");
-
-		when(_store.getServiceDef(id)).thenThrow(new Exception());
-		assertFalse(_validator.isValid(_serviceDef, Action.UPDATE, _failures));
-		_utils.checkFailureForSemanticError(_failures, "id");
-	}
-	
-	@Test
-	public final void testIsValid_failures_nameId_create() throws Exception {
-		// service shouldn't exist with the name
-		RangerServiceDef existingServiceDef = mock(RangerServiceDef.class);
-		when(_store.getServiceDefByName("existing-service")).thenReturn(existingServiceDef);
-		when(_serviceDef.getName()).thenReturn("existing-service");
-		_failures.clear(); assertFalse(_validator.isValid(_serviceDef, Action.CREATE, _failures));
-		_utils.checkFailureForSemanticError(_failures, "name");
-	}
-	
-	@Test
-	public final void testIsValid_failures_nameId_update() throws Exception {
-		
-		// update: if service exists with the same name then it can't point to a different service
-		Long id = 7L;
-		when(_serviceDef.getId()).thenReturn(id);
-		RangerServiceDef existingServiceDef = mock(RangerServiceDef.class);
-		when(existingServiceDef.getId()).thenReturn(id);
-		when(_store.getServiceDef(id)).thenReturn(existingServiceDef);
-		
-		String name = "aServiceDef";
-		when(_serviceDef.getName()).thenReturn(name);
-		RangerServiceDef anotherExistingServiceDef = mock(RangerServiceDef.class);
-		Long anotherId = 49L;
-		when(anotherExistingServiceDef.getId()).thenReturn(anotherId);
-		when(_store.getServiceDefByName(name)).thenReturn(anotherExistingServiceDef);
-		
-		assertFalse(_validator.isValid(_serviceDef, Action.UPDATE, _failures));
-		_utils.checkFailureForSemanticError(_failures, "id/name");
-	}
-
-	final Object[][] accessTypes_bad_unknownType = new Object[][] {
-			{ "read",  null },                                // ok, null implied grants
-			{ "write", new String[] {   } },                  // ok, empty implied grants
-			{ "admin", new String[] { "ReaD",  "execute" } }  // non-existent access type (execute), read is good (case should not matter)
-	};
-
-	final Object[][] accessTypes_bad_selfReference = new Object[][] {
-			{ "read",  null },                                // ok, null implied grants
-			{ "write", new String[] {   } },                  // ok, empty implied grants
-			{ "admin", new String[] { "write", "admin" } }  // non-existent access type (execute)
-	};
-
-	@Test
-	public final void test_isValidAccessTypes_happyPath() {
-		List<RangerAccessTypeDef> input = _utils.createAccessTypeDefs(accessTypes_good);
-		assertTrue(_validator.isValidAccessTypes(input, _failures));
-		assertTrue(_failures.isEmpty());
-	}
-	
-	@Test
-	public final void test_isValidAccessTypes_failures() {
-		// sending in empty null access type defs is ok
-		assertTrue(_validator.isValidAccessTypes(null, _failures));
-		assertTrue(_failures.isEmpty());
-		
-		List<RangerAccessTypeDef> input = new ArrayList<RangerAccessTypeDef>();
-		_failures.clear(); assertTrue(_validator.isValidAccessTypes(input, _failures));
-		assertTrue(_failures.isEmpty());
-
-		// null/empty access types
-		List<RangerAccessTypeDef> accessTypeDefs = _utils.createAccessTypeDefs(new String[] { null, "", "		" });
-		_failures.clear(); assertFalse(_validator.isValidAccessTypes(accessTypeDefs, _failures));
-		_utils.checkFailureForMissingValue(_failures, "access type name");
-		
-		// duplicate access types
-		accessTypeDefs = _utils.createAccessTypeDefs(new String[] { "read", "write", "execute", "read" } );
-		_failures.clear(); assertFalse(_validator.isValidAccessTypes(accessTypeDefs, _failures));
-		_utils.checkFailureForSemanticError(_failures, "access type name", "read");
-		
-		// duplicate access types - case-insensitive
-		accessTypeDefs = _utils.createAccessTypeDefs(new String[] { "read", "write", "execute", "READ" } );
-		_failures.clear(); assertFalse(_validator.isValidAccessTypes(accessTypeDefs, _failures));
-		_utils.checkFailureForSemanticError(_failures, "access type name", "READ");
-		
-		// unknown access type in implied grants list
-		accessTypeDefs = _utils.createAccessTypeDefs(accessTypes_bad_unknownType);
-		_failures.clear(); assertFalse(_validator.isValidAccessTypes(accessTypeDefs, _failures));
-		_utils.checkFailureForSemanticError(_failures, "implied grants", "execute");
-		
-		// access type with implied grant referring to itself
-		accessTypeDefs = _utils.createAccessTypeDefs(accessTypes_bad_selfReference);
-		_failures.clear(); assertFalse(_validator.isValidAccessTypes(accessTypeDefs, _failures));
-		_utils.checkFailureForSemanticError(_failures, "implied grants", "admin");
-	}
-	
-	final Map<String, String[]> enums_bad_enumName_null = ImmutableMap.of(
-			"authentication-type", new String[] { "simple", "kerberos" },
-			"time-unit", new String[] { "day", "hour", "minute" },
-			"null", new String[] { "foo", "bar", "tar" } // null enum-name -- "null" is a special value that leads to a null enum name
-	);
-	
-	final Map<String, String[]> enums_bad_enumName_blank = ImmutableMap.of(
-			"authentication-type", new String[] { "simple", "kerberos" },
-			"time-unit", new String[] { "day", "hour", "minute" },
-			"  ", new String[] { "foo", "bar", "tar" } // enum name is all spaces
-	);
-	
-	final Map<String, String[]> enums_bad_Elements_empty = ImmutableMap.of(
-			"authentication-type", new String[] { "simple", "kerberos" },
-			"time-unit", new String[] { "day", "hour", "minute" },
-			"anEnum", new String[] { } // enum elements collection is empty
-	);
-	
-	final Map<String, String[]> enums_bad_enumName_duplicate_exact = ImmutableMap.of(
-			"authentication-type", new String[] { "simple", "kerberos" },
-			"time-unit", new String[] { "day", "hour", "minute" }
-	);
-	
-	final Map<String, String[]> enums_bad_enumName_duplicate_differentCase = ImmutableMap.of(
-			"authentication-type", new String[] { "simple", "kerberos" },
-			"time-unit", new String[] { "day", "hour", "minute" },
-			"Authentication-Type", new String[] { } // duplicate enum-name different in case
-	);
-	
-	@Test
-	public final void test_isValidEnums_happyPath() {
-		List<RangerEnumDef> input = _utils.createEnumDefs(enums_good);
-		assertTrue(_validator.isValidEnums(input, _failures));
-		assertTrue(_failures.isEmpty());
-	}
-	
-	@Test
-	public final void test_isValidEnums_failures() {
-		// null elements in enum def list are a failure
-		List<RangerEnumDef> input = _utils.createEnumDefs(enums_good);
-		input.add(null);
-		assertFalse(_validator.isValidEnums(input, _failures));
-		_utils.checkFailureForMissingValue(_failures, "enum def");
-		
-		// enum names should be valid
-		input = _utils.createEnumDefs(enums_bad_enumName_null);
-		_failures.clear(); assertFalse(_validator.isValidEnums(input, _failures));
-		_utils.checkFailureForMissingValue(_failures, "enum def name");
-
-		input = _utils.createEnumDefs(enums_bad_enumName_blank);
-		_failures.clear(); assertFalse(_validator.isValidEnums(input, _failures));
-		_utils.checkFailureForMissingValue(_failures, "enum def name");
-		
-		// enum elements collection should not be null or empty
-		input = _utils.createEnumDefs(enums_good);
-		RangerEnumDef anEnumDef = mock(RangerEnumDef.class);
-		when(anEnumDef.getName()).thenReturn("anEnum");
-		when(anEnumDef.getElements()).thenReturn(null);
-		input.add(anEnumDef);
-		_failures.clear(); assertFalse(_validator.isValidEnums(input, _failures));
-		_utils.checkFailureForMissingValue(_failures, "enum values", "anEnum");
-
-		input = _utils.createEnumDefs(enums_bad_Elements_empty);
-		_failures.clear(); assertFalse(_validator.isValidEnums(input, _failures));
-		_utils.checkFailureForMissingValue(_failures, "enum values", "anEnum");
-	
-		// enum names should be distinct -- exact match
-		input = _utils.createEnumDefs(enums_good);
-		// add an element with same name as the first element
-		String name = input.iterator().next().getName();
-		when(anEnumDef.getName()).thenReturn(name);
-		List<RangerEnumElementDef> elementDefs = _utils.createEnumElementDefs(new String[] {"val1", "val2"}); 
-		when(anEnumDef.getElements()).thenReturn(elementDefs);
-		input.add(anEnumDef);
-		_failures.clear(); assertFalse(_validator.isValidEnums(input, _failures));
-		_utils.checkFailureForSemanticError(_failures, "enum def name", name);
-
-		// enum names should be distinct -- case insensitive
-		input = _utils.createEnumDefs(enums_bad_enumName_duplicate_differentCase);
-		_failures.clear(); assertFalse(_validator.isValidEnums(input, _failures));
-		_utils.checkFailureForSemanticError(_failures, "enum def name", "Authentication-Type");
-	
-		// enum default index should be right
-		input = _utils.createEnumDefs(enums_good);
-		// set the index of 1st on to be less than 0
-		when(input.iterator().next().getDefaultIndex()).thenReturn(-1);
-		_failures.clear(); assertFalse(_validator.isValidEnums(input, _failures));
-		_utils.checkFailureForSemanticError(_failures, "enum default index", "authentication-type");
-		// set the index to be more than number of elements
-		when(input.iterator().next().getDefaultIndex()).thenReturn(2);
-		_failures.clear(); assertFalse(_validator.isValidEnums(input, _failures));
-		_utils.checkFailureForSemanticError(_failures, "enum default index", "authentication-type");
-	}
-
-	@Test
-	public final void test_isValidEnumElements_happyPath() {
-		List<RangerEnumElementDef> input = _utils.createEnumElementDefs(new String[] { "simple", "kerberos" });
-		assertTrue(_validator.isValidEnumElements(input, _failures, "anEnum"));
-		assertTrue(_failures.isEmpty());
-	}
-
-	@Test
-	public final void test_isValidEnumElements_failures() {
-		// enum element collection should not have nulls in it
-		List<RangerEnumElementDef> input = _utils.createEnumElementDefs(new String[] { "simple", "kerberos" });
-		input.add(null);
-		assertFalse(_validator.isValidEnumElements(input, _failures, "anEnum"));
-		_utils.checkFailureForMissingValue(_failures, "enum element", "anEnum");
-
-		// element names can't be null/empty
-		input = _utils.createEnumElementDefs(new String[] { "simple", "kerberos", null });
-		_failures.clear(); assertFalse(_validator.isValidEnumElements(input, _failures, "anEnum"));
-		_utils.checkFailureForMissingValue(_failures, "enum element name", "anEnum");
-
-		input = _utils.createEnumElementDefs(new String[] { "simple", "kerberos", "		" }); // two tabs
-		_failures.clear(); assertFalse(_validator.isValidEnumElements(input, _failures, "anEnum"));
-		_utils.checkFailureForMissingValue(_failures, "enum element name", "anEnum");
-		
-		// element names should be distinct - case insensitive
-		input = _utils.createEnumElementDefs(new String[] { "simple", "kerberos", "kerberos" }); // duplicate name - exact match
-		_failures.clear(); assertFalse(_validator.isValidEnumElements(input, _failures, "anEnum"));
-		_utils.checkFailureForSemanticError(_failures, "enum element name", "anEnum");
-		
-		input = _utils.createEnumElementDefs(new String[] { "simple", "kerberos", "kErbErOs" }); // duplicate name - different case
-		_failures.clear(); assertFalse(_validator.isValidEnumElements(input, _failures, "anEnum"));
-		_utils.checkFailureForSemanticError(_failures, "enum element name", "anEnum");
-	}
-	
-	private ValidationTestUtils _utils = new ValidationTestUtils();
-	RangerServiceDef _serviceDef;
-	List<ValidationFailureDetails> _failures;
-	ServiceStore _store;
-	RangerServiceDefValidator _validator;
-}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/security-admin/src/test/java/org/apache/ranger/rest/TestRangerServiceValidator.java
----------------------------------------------------------------------
diff --git a/security-admin/src/test/java/org/apache/ranger/rest/TestRangerServiceValidator.java b/security-admin/src/test/java/org/apache/ranger/rest/TestRangerServiceValidator.java
deleted file mode 100644
index 6465cca..0000000
--- a/security-admin/src/test/java/org/apache/ranger/rest/TestRangerServiceValidator.java
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF 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.apache.ranger.rest;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.ranger.plugin.model.RangerService;
-import org.apache.ranger.plugin.model.RangerServiceDef;
-import org.apache.ranger.plugin.model.RangerServiceDef.RangerServiceConfigDef;
-import org.apache.ranger.plugin.store.ServiceStore;
-import org.apache.ranger.rest.RangerServiceValidator;
-import org.apache.ranger.rest.ValidationFailureDetails;
-import org.apache.ranger.rest.RangerValidator.Action;
-import org.junit.Before;
-import org.junit.Test;
-
-public class TestRangerServiceValidator {
-	
-	final Action[] cud = new Action[] { Action.CREATE, Action.UPDATE, Action.DELETE };
-	final Action[] cu = new Action[] { Action.CREATE, Action.UPDATE };
-	final Action[] ud = new Action[] { Action.UPDATE, Action.DELETE };
-
-	@Before
-	public void before() {
-		_store = mock(ServiceStore.class);
-		_action = Action.CREATE; // by default we set action to create
-		_validator = new RangerServiceValidator(_store);
-	}
-
-	void checkFailure_isValid(RangerServiceValidator validator, RangerService service, Action action, List<ValidationFailureDetails> failures, String errorType, String field) {
-		checkFailure_isValid(validator, service, action, failures, errorType, field, null);
-	}
-	
-	void checkFailure_isValid(RangerServiceValidator validator, RangerService service, Action action, List<ValidationFailureDetails> failures, String errorType, String field, String subField) {
-		failures.clear();
-		assertFalse(validator.isValid(service, action, failures));
-		switch (errorType) {
-		case "missing":
-			_utils.checkFailureForMissingValue(failures, field, subField);
-			break;
-		case "semantic":
-			_utils.checkFailureForSemanticError(failures, field, subField);
-			break;
-		case "internal error":
-			_utils.checkFailureForInternalError(failures);
-			break;
-		default:
-			fail("Unsupported errorType[" + errorType + "]");
-			break;
-		}
-	}
-	
-	@Test
-	public void testIsValid_failures() throws Exception {
-		RangerService service = mock(RangerService.class);
-		// passing in a null service to the check itself is an error
-		assertFalse(_validator.isValid((RangerService)null, _action, _failures));
-		_utils.checkFailureForMissingValue(_failures, "service");
-
-		// id is required for update
-		when(service.getId()).thenReturn(null);
-		// let's verify the failure and the sort of error information that is returned (for one of these)
-		// assert that among the failure reason is one about id being missing.
-		checkFailure_isValid(_validator, service, Action.UPDATE, _failures, "missing", "id");
-		when(service.getId()).thenReturn(7L);
-
-		for (Action action : cu) {
-			// null, empty of blank name renders a service invalid
-			for (String name : new String[] { null, "", " 	" }) { // spaces and tabs
-				when(service.getName()).thenReturn(name);
-				checkFailure_isValid(_validator, service, action, _failures, "missing", "name");
-			}
-			// same is true for the type
-			for (String type : new String[] { null, "", "    " }) {
-				when(service.getType()).thenReturn(type);
-				checkFailure_isValid(_validator, service, action, _failures, "missing", "type");
-			}
-		}
-		when(service.getName()).thenReturn("aName");
-
-		// if non-empty, then the type should exist!
-		when(_store.getServiceDefByName("null-type")).thenReturn(null);
-		when(_store.getServiceDefByName("throwing-type")).thenThrow(new Exception());
-		for (Action action : cu) {
-			for (String type : new String[] { "null-type", "throwing-type" }) {
-				when(service.getType()).thenReturn(type);
-				checkFailure_isValid(_validator, service, action, _failures, "semantic", "type");
-			}
-		}
-		when(service.getType()).thenReturn("aType");
-		RangerServiceDef serviceDef = mock(RangerServiceDef.class);
-		when(_store.getServiceDefByName("aType")).thenReturn(serviceDef);
-		
-		// Create: No service should exist matching its id and/or name
-		RangerService anExistingService = mock(RangerService.class);
-		when(_store.getServiceByName("aName")).thenReturn(anExistingService);
-		checkFailure_isValid(_validator, service, Action.CREATE, _failures, "semantic", "name");
-
-		// Update: service should exist matching its id and name specified should not belong to a different service
-		when(_store.getService(7L)).thenReturn(null);
-		when(_store.getServiceByName("aName")).thenReturn(anExistingService);
-		checkFailure_isValid(_validator, service, Action.UPDATE, _failures, "semantic", "id");
-
-		when(_store.getService(7L)).thenReturn(anExistingService);
-		RangerService anotherExistingService = mock(RangerService.class);
-		when(anotherExistingService.getId()).thenReturn(49L);
-		when(_store.getServiceByName("aName")).thenReturn(anotherExistingService);
-		checkFailure_isValid(_validator, service, Action.UPDATE, _failures, "semantic", "id/name");
-	}
-	
-	@Test
-	public void test_isValid_missingRequiredParameter() throws Exception {
-		// Create/Update: simulate a condition where required parameters are missing
-		Object[][] input = new Object[][] {
-				{ "param1", true },
-				{ "param2", true },
-				{ "param3", false },
-				{ "param4", false },
-		};
-		List<RangerServiceConfigDef> configDefs = _utils.createServiceConditionDefs(input);
-		RangerServiceDef serviceDef = mock(RangerServiceDef.class);
-		when(serviceDef.getConfigs()).thenReturn(configDefs);
-		// wire this service def into store
-		when(_store.getServiceDefByName("aType")).thenReturn(serviceDef);
-		// create a service with some require parameters missing
-		RangerService service = mock(RangerService.class);
-		when(service.getType()).thenReturn("aType");
-		when(service.getName()).thenReturn("aName");
-		// required parameters param2 is missing
-		String[] params = new String[] { "param1", "param3", "param4", "param5" };
-		Map<String, String> paramMap = _utils.createMap(params);
-		when(service.getConfigs()).thenReturn(paramMap);
-		// service does not exist in the store
-		when(_store.getServiceByName("aService")).thenReturn(null);
-		for (Action action : cu) {
-			// it should be invalid
-			checkFailure_isValid(_validator, service, action, _failures, "missing", "configuration", "param2");
-		}
-	}
-
-	@Test
-	public void test_isValid_happyPath() throws Exception {
-		// create a service def with some required parameters 
-		Object[][] serviceDefInput = new Object[][] {
-				{ "param1", true },
-				{ "param2", true },
-				{ "param3", false },
-				{ "param4", false },
-				{ "param5", true },
-		};
-		List<RangerServiceConfigDef> configDefs = _utils.createServiceConditionDefs(serviceDefInput);
-		RangerServiceDef serviceDef = mock(RangerServiceDef.class);
-		when(serviceDef.getConfigs()).thenReturn(configDefs);
-		// create a service with some parameters on it
-		RangerService service = mock(RangerService.class);
-		when(service.getName()).thenReturn("aName");
-		when(service.getType()).thenReturn("aType");
-		// contains an extra parameter (param6) and one optional is missing(param4)
-		String[] configs = new String[] { "param1", "param2", "param3", "param5", "param6" };
-		Map<String, String> configMap = _utils.createMap(configs);  
-		when(service.getConfigs()).thenReturn(configMap);
-		// wire then into the store
-		// service does not exists
-		when(_store.getServiceByName("aName")).thenReturn(null);
-		// service def exists
-		when(_store.getServiceDefByName("aType")).thenReturn(serviceDef);
-
-		assertTrue(_validator.isValid(service, Action.CREATE, _failures));
-
-		// for update to work the only additional requirement is that id is required and service should exist
-		// if name is not null and it points to a service then it should match the id
-		when(service.getId()).thenReturn(7L);
-		RangerService existingService = mock(RangerService.class);
-		when(existingService.getId()).thenReturn(7L);
-		when(_store.getService(7L)).thenReturn(existingService);
-		when(_store.getServiceByName("aName")).thenReturn(existingService);
-		assertTrue(_validator.isValid(service, Action.UPDATE, _failures));
-		// name need not point to a service for update to work, of course.
-		when(_store.getServiceByName("aName")).thenReturn(null);
-		assertTrue(_validator.isValid(service, Action.UPDATE, _failures));
-	}
-
-	@Test
-	public void test_isValid_withId_errorConditions() throws Exception {
-		// api that takes in long is only supported for delete currently
-		assertFalse(_validator.isValid(1L, Action.CREATE, _failures));
-		_utils.checkFailureForInternalError(_failures);
-		// passing in a null id is a failure!
-		_validator = new RangerServiceValidator(_store);
-		_failures.clear(); assertFalse(_validator.isValid((Long)null, Action.DELETE, _failures));
-		_utils.checkFailureForMissingValue(_failures, "id");
-		// if service with that id does not exist then that, too, is a failure
-		when(_store.getService(1L)).thenReturn(null);
-		when(_store.getService(2L)).thenThrow(new Exception());
-		_failures.clear(); assertFalse(_validator.isValid(1L, Action.DELETE, _failures));
-		_utils.checkFailureForSemanticError(_failures, "id");
-
-		_failures.clear(); assertFalse(_validator.isValid(2L, Action.DELETE, _failures));
-		_utils.checkFailureForSemanticError(_failures, "id");
-	}
-	
-	@Test
-	public void test_isValid_withId_happyPath() throws Exception {
-		_validator = new RangerServiceValidator(_store);
-		RangerService service = mock(RangerService.class);
-		when(_store.getService(1L)).thenReturn(service);
-		assertTrue(_validator.isValid(1L, Action.DELETE, _failures));
-	}
-	
-	private ServiceStore _store;
-	private RangerServiceValidator _validator;
-	private Action _action;
-	private ValidationTestUtils _utils = new ValidationTestUtils();
-	private List<ValidationFailureDetails> _failures = new ArrayList<ValidationFailureDetails>();
-}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/security-admin/src/test/java/org/apache/ranger/rest/TestRangerValidator.java
----------------------------------------------------------------------
diff --git a/security-admin/src/test/java/org/apache/ranger/rest/TestRangerValidator.java b/security-admin/src/test/java/org/apache/ranger/rest/TestRangerValidator.java
deleted file mode 100644
index cbaaf60..0000000
--- a/security-admin/src/test/java/org/apache/ranger/rest/TestRangerValidator.java
+++ /dev/null
@@ -1,476 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF 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.apache.ranger.rest;
-
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.ranger.plugin.model.RangerPolicy;
-import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
-import org.apache.ranger.plugin.model.RangerService;
-import org.apache.ranger.plugin.model.RangerServiceDef;
-import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef;
-import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumDef;
-import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
-import org.apache.ranger.plugin.model.RangerServiceDef.RangerServiceConfigDef;
-import org.apache.ranger.plugin.store.ServiceStore;
-import org.apache.ranger.plugin.util.SearchFilter;
-import org.apache.ranger.rest.RangerValidator;
-import org.apache.ranger.rest.RangerValidator.Action;
-import org.junit.Before;
-import org.junit.Test;
-
-import com.google.common.collect.Maps;
-
-public class TestRangerValidator {
-
-	static class RangerValidatorForTest extends RangerValidator {
-
-		public RangerValidatorForTest(ServiceStore store) {
-			super(store);
-		}
-		
-		boolean isValid(String behavior) {
-			boolean valid;
-			if (behavior.equals("valid")) {
-				valid = true;
-			} else {
-				valid = false;
-			}
-			return valid;
-		}
-	}
-	
-	@Before
-	public void before() {
-		_store = mock(ServiceStore.class);
-		_validator = new RangerValidatorForTest(_store);
-	}
-
-	@Test
-	public void test_ctor_firewalling() {
-		try {
-			// service store can't be null during construction  
-			new RangerValidatorForTest(null);
-			fail("Should have thrown exception!");
-		} catch (IllegalArgumentException e) {
-			// expected exception
-		}
-	}
-	
-	@Test
-	public void test_validate() {
-		// default implementation should fail.  This is abstract class.  Sub-class must do something sensible with isValid
-		try {
-			_validator.validate(1L, Action.CREATE);
-			fail("Should have thrown exception!");
-		} catch (Exception e) {
-			// ok expected exception
-			String message = e.getMessage();
-			assertTrue(message.contains("internal error"));
-		}
-	}
-
-	@Test
-	public void test_getServiceConfigParameters() {
-		// reasonable protection against null values
-		Set<String> parameters = _validator.getServiceConfigParameters(null);
-		assertNotNull(parameters);
-		assertTrue(parameters.isEmpty());
-		
-		RangerService service = mock(RangerService.class);
-		when(service.getConfigs()).thenReturn(null);
-		parameters = _validator.getServiceConfigParameters(service);
-		assertNotNull(parameters);
-		assertTrue(parameters.isEmpty());
-		
-		when(service.getConfigs()).thenReturn(new HashMap<String, String>());
-		parameters = _validator.getServiceConfigParameters(service);
-		assertNotNull(parameters);
-		assertTrue(parameters.isEmpty());
-
-		String[] keys = new String[] { "a", "b", "c" };
-		Map<String, String> map = _utils.createMap(keys);
-		when(service.getConfigs()).thenReturn(map);
-		parameters = _validator.getServiceConfigParameters(service);
-		for (String key: keys) {
-			assertTrue("key", parameters.contains(key));
-		}
-	}
-	
-	@Test
-	public void test_getRequiredParameters() {
-		// reasonable protection against null things
-		Set<String> parameters = _validator.getRequiredParameters(null);
-		assertNotNull(parameters);
-		assertTrue(parameters.isEmpty());
-
-		RangerServiceDef serviceDef = mock(RangerServiceDef.class);
-		when(serviceDef.getConfigs()).thenReturn(null);
-		parameters = _validator.getRequiredParameters(null);
-		assertNotNull(parameters);
-		assertTrue(parameters.isEmpty());
-
-		List<RangerServiceConfigDef> configs = new ArrayList<RangerServiceDef.RangerServiceConfigDef>();
-		when(serviceDef.getConfigs()).thenReturn(configs);
-		parameters = _validator.getRequiredParameters(null);
-		assertNotNull(parameters);
-		assertTrue(parameters.isEmpty());
-		
-		Object[][] input = new Object[][] {
-				{ "param1", false },
-				{ "param2", true },
-				{ "param3", true },
-				{ "param4", false },
-		};
-		configs = _utils.createServiceConditionDefs(input);
-		when(serviceDef.getConfigs()).thenReturn(configs);
-		parameters = _validator.getRequiredParameters(serviceDef);
-		assertTrue("result does not contain: param2", parameters.contains("param2"));
-		assertTrue("result does not contain: param3", parameters.contains("param3"));
-	}
-	
-	@Test
-	public void test_getServiceDef() {
-		try {
-			// if service store returns null or throws an exception then service is deemed invalid
-			when(_store.getServiceDefByName("return null")).thenReturn(null);
-			when(_store.getServiceDefByName("throw")).thenThrow(new Exception());
-			RangerServiceDef serviceDef = mock(RangerServiceDef.class);
-			when(_store.getServiceDefByName("good-service")).thenReturn(serviceDef);
-		} catch (Exception e) {
-			e.printStackTrace();
-			fail("Unexpected exception during mocking!");
-		}
-		
-		assertNull(_validator.getServiceDef("return null"));
-		assertNull(_validator.getServiceDef("throw"));
-		assertFalse(_validator.getServiceDef("good-service") == null);
-	}
-
-	@Test
-	public void test_getPolicy() throws Exception {
-		// if service store returns null or throws an exception then return null policy
-		when(_store.getPolicy(1L)).thenReturn(null);
-		when(_store.getPolicy(2L)).thenThrow(new Exception());
-		RangerPolicy policy = mock(RangerPolicy.class);
-		when(_store.getPolicy(3L)).thenReturn(policy);
-		
-		assertNull(_validator.getPolicy(1L));
-		assertNull(_validator.getPolicy(2L));
-		assertTrue(_validator.getPolicy(3L) != null);
-	}
-
-	@Test
-	public void test_getService_byId() throws Exception {
-		// if service store returns null or throws an exception then service is deemed invalid
-		when(_store.getService(1L)).thenReturn(null);
-		when(_store.getService(2L)).thenThrow(new Exception());
-		RangerService service = mock(RangerService.class);
-		when(_store.getService(3L)).thenReturn(service);
-		
-		assertNull(_validator.getService(1L));
-		assertNull(_validator.getService(2L));
-		assertTrue(_validator.getService(3L) != null);
-	}
-
-	@Test
-	public void test_getService() {
-		try {
-			// if service store returns null or throws an exception then service is deemed invalid
-			when(_store.getServiceByName("return null")).thenReturn(null);
-			when(_store.getServiceByName("throw")).thenThrow(new Exception());
-			RangerService service = mock(RangerService.class);
-			when(_store.getServiceByName("good-service")).thenReturn(service);
-		} catch (Exception e) {
-			e.printStackTrace();
-			fail("Unexpected exception during mocking!");
-		}
-		
-		assertNull(_validator.getService("return null"));
-		assertNull(_validator.getService("throw"));
-		assertFalse(_validator.getService("good-service") == null);
-	}
-	
-	@Test
-	public void test_getAccessTypes() {
-		// passing in null service def
-		Set<String> accessTypes = _validator.getAccessTypes((RangerServiceDef)null);
-		assertTrue(accessTypes.isEmpty());
-		// that has null or empty access type def
-		RangerServiceDef serviceDef = mock(RangerServiceDef.class);
-		when(serviceDef.getAccessTypes()).thenReturn(null);
-		accessTypes = _validator.getAccessTypes(serviceDef);
-		assertTrue(accessTypes.isEmpty());
-
-		List<RangerAccessTypeDef> accessTypeDefs = new ArrayList<RangerServiceDef.RangerAccessTypeDef>();
-		when(serviceDef.getAccessTypes()).thenReturn(accessTypeDefs);
-		accessTypes = _validator.getAccessTypes(serviceDef);
-		assertTrue(accessTypes.isEmpty());
-		
-		// having null accesstypedefs
-		accessTypeDefs.add(null);
-		accessTypes = _validator.getAccessTypes(serviceDef);
-		assertTrue(accessTypes.isEmpty());
-		
-		// access type defs with null empty blank names are skipped, spaces within names are preserved
-		String[] names = new String[] { null, "", "a", "  ", "b ", "		", " C", "	D	" };
-		accessTypeDefs.addAll(_utils.createAccessTypeDefs(names));
-		accessTypes = _validator.getAccessTypes(serviceDef);
-		assertEquals(4, accessTypes.size());
-		assertTrue(accessTypes.contains("a"));
-		assertTrue(accessTypes.contains("b "));
-		assertTrue(accessTypes.contains(" c"));
-		assertTrue(accessTypes.contains("	d	"));
-	}
-	
-	@Test
-	public void test_getResourceNames() {
-		// passing in null service def
-		Set<String> accessTypes = _validator.getMandatoryResourceNames((RangerServiceDef)null);
-		assertTrue(accessTypes.isEmpty());
-		// that has null or empty access type def
-		RangerServiceDef serviceDef = mock(RangerServiceDef.class);
-		when(serviceDef.getResources()).thenReturn(null);
-		accessTypes = _validator.getMandatoryResourceNames(serviceDef);
-		assertTrue(accessTypes.isEmpty());
-
-		List<RangerResourceDef> resourceDefs = new ArrayList<RangerResourceDef>();
-		when(serviceDef.getResources()).thenReturn(resourceDefs);
-		accessTypes = _validator.getMandatoryResourceNames(serviceDef);
-		assertTrue(accessTypes.isEmpty());
-		
-		// having null accesstypedefs
-		resourceDefs.add(null);
-		accessTypes = _validator.getMandatoryResourceNames(serviceDef);
-		assertTrue(accessTypes.isEmpty());
-		
-		// access type defs with null empty blank names are skipped, spaces within names are preserved
-		Object[][] data = {
-				{ "a", true },  // all good
-				null,           // this should put a null element in the resource def!
-				{ "b", null },  // mandatory field is null, i.e. false
-				{ "c", false }, // non-mandatory field false - upper case
-				{ "D", true },  // resource specified in upper case
-				{ "E", false }, // all good
-		};
-		resourceDefs.addAll(_utils.createResourceDefs(data));
-		accessTypes = _validator.getMandatoryResourceNames(serviceDef);
-		assertEquals(2, accessTypes.size());
-		assertTrue(accessTypes.contains("a"));
-		assertTrue(accessTypes.contains("d")); // name should come back lower case
-		
-		accessTypes = _validator.getAllResourceNames(serviceDef);
-		assertEquals(5, accessTypes.size());
-		assertTrue(accessTypes.contains("b"));
-		assertTrue(accessTypes.contains("c"));
-		assertTrue(accessTypes.contains("e"));
-	}
-
-	@Test
-	public void test_getValidationRegExes() {
-		// passing in null service def
-		Map<String, String> regExMap = _validator.getValidationRegExes((RangerServiceDef)null);
-		assertTrue(regExMap.isEmpty());
-		// that has null or empty access type def
-		RangerServiceDef serviceDef = mock(RangerServiceDef.class);
-		when(serviceDef.getResources()).thenReturn(null);
-		regExMap = _validator.getValidationRegExes(serviceDef);
-		assertTrue(regExMap.isEmpty());
-
-		List<RangerResourceDef> resourceDefs = new ArrayList<RangerResourceDef>();
-		when(serviceDef.getResources()).thenReturn(resourceDefs);
-		regExMap = _validator.getValidationRegExes(serviceDef);
-		assertTrue(regExMap.isEmpty());
-		
-		// having null accesstypedefs
-		resourceDefs.add(null);
-		regExMap = _validator.getValidationRegExes(serviceDef);
-		assertTrue(regExMap.isEmpty());
-		
-		// access type defs with null empty blank names are skipped, spaces within names are preserved
-		String[][] data = {
-				{ "a", null },     // null-regex
-				null,              // this should put a null element in the resource def!
-				{ "b", "regex1" }, // valid
-				{ "c", "" },       // empty regex
-				{ "d", "regex2" }, // valid
-				{ "e", "   " },    // blank regex
-				{ "f", "regex3" }, // all good
-		};
-		resourceDefs.addAll(_utils.createResourceDefsWithRegEx(data));
-		regExMap = _validator.getValidationRegExes(serviceDef);
-		assertEquals(3, regExMap.size());
-		assertEquals("regex1", regExMap.get("b"));
-		assertEquals("regex2", regExMap.get("d"));
-		assertEquals("regex3", regExMap.get("f"));
-	}
-
-	@Test
-	public void test_getPolicyResources() {
-		
-		Set<String> result;
-		RangerPolicy policy = null;
-		// null policy
-		result = _validator.getPolicyResources(null);
-		assertTrue(result != null);
-		assertTrue(result.isEmpty());
-		// null resource map
-		policy = mock(RangerPolicy.class);
-		when(policy.getResources()).thenReturn(null);
-		result = _validator.getPolicyResources(null);
-		assertTrue(result != null);
-		assertTrue(result.isEmpty());
-		// empty resource map
-		Map<String, RangerPolicyResource> input = Maps.newHashMap();
-		when(policy.getResources()).thenReturn(input);
-		result = _validator.getPolicyResources(policy);
-		assertTrue(result != null);
-		assertTrue(result.isEmpty());
-		// known resource map
-		input.put("r1", mock(RangerPolicyResource.class));
-		input.put("R2", mock(RangerPolicyResource.class));
-		result = _validator.getPolicyResources(policy);
-		assertEquals(2, result.size());
-		assertTrue("r1", result.contains("r1"));
-		assertTrue("R2", result.contains("r2")); // result should lowercase the resource-names
-	}
-
-	@Test
-	public void test_getIsAuditEnabled() {
-		// null policy
-		RangerPolicy policy = null;
-		boolean result = _validator.getIsAuditEnabled(policy);
-		assertFalse(result);
-		// null isAuditEnabled Boolean is supposed to be TRUE!!
-		policy = mock(RangerPolicy.class);
-		when(policy.getIsAuditEnabled()).thenReturn(null);
-		result = _validator.getIsAuditEnabled(policy);
-		assertTrue(result);
-		// non-null value
-		when(policy.getIsAuditEnabled()).thenReturn(Boolean.FALSE);
-		result = _validator.getIsAuditEnabled(policy);
-		assertFalse(result);
-
-		when(policy.getIsAuditEnabled()).thenReturn(Boolean.TRUE);
-		result = _validator.getIsAuditEnabled(policy);
-		assertTrue(result);
-	}
-
-	@Test
-	public void test_getPolicies() throws Exception {
-
-		// returns null when store returns null
-		String policyName = "aPolicy";
-		String serviceName = "aService";
-		SearchFilter filter = new SearchFilter();
-		filter.setParam(SearchFilter.POLICY_NAME, policyName);
-		filter.setParam(SearchFilter.SERVICE_NAME, serviceName);
-		
-		when(_store.getPolicies(filter)).thenReturn(null);
-		List<RangerPolicy> result = _validator.getPolicies(policyName, serviceName);
-		// validate store is queried with both parameters
-		verify(_store).getPolicies(filter);
-		assertNull(result);
-
-		// returns null if store throws an exception
-		when(_store.getPolicies(filter)).thenThrow(new Exception());
-		result = _validator.getPolicies(policyName, serviceName);
-		assertNull(result);
-	}
-	
-	@Test
-	public void test_getServiceDef_byId() throws Exception {
-		// if service store returns null or throws an exception then service is deemed invalid
-		when(_store.getServiceDef(1L)).thenReturn(null);
-		when(_store.getServiceDef(2L)).thenThrow(new Exception());
-		RangerServiceDef serviceDef = mock(RangerServiceDef.class);
-		when(_store.getServiceDef(3L)).thenReturn(serviceDef);
-		
-		assertNull(_validator.getServiceDef(1L));
-		assertNull(_validator.getServiceDef(2L));
-		assertTrue(_validator.getServiceDef(3L) != null);
-	}
-
-	@Test
-	public void test_getEnumDefaultIndex() {
-		RangerEnumDef enumDef = mock(RangerEnumDef.class);
-		assertEquals(-1, _validator.getEnumDefaultIndex(null));
-		when(enumDef.getDefaultIndex()).thenReturn(null);
-		assertEquals(0, _validator.getEnumDefaultIndex(enumDef));
-		when(enumDef.getDefaultIndex()).thenReturn(-5);
-		assertEquals(-5, _validator.getEnumDefaultIndex(enumDef));
-	}
-	
-	@Test
-	public void test_getImpliedGrants() {
-		
-		// passing in null gets back a null
-		Collection<String> result = _validator.getImpliedGrants(null);
-		assertNull(result);
-		
-		// null or empty implied grant collection gets back an empty collection
-		RangerAccessTypeDef accessTypeDef = mock(RangerAccessTypeDef.class);
-		when(accessTypeDef.getImpliedGrants()).thenReturn(null);
-		result = _validator.getImpliedGrants(accessTypeDef);
-		assertTrue(result.isEmpty());
-		
-		List<String> impliedGrants = new ArrayList<String>();
-		when(accessTypeDef.getImpliedGrants()).thenReturn(impliedGrants);
-		result = _validator.getImpliedGrants(accessTypeDef);
-		assertTrue(result.isEmpty());
-
-		// null/empty values come back as is
-		impliedGrants = Arrays.asList(new String[] { null, "", " ", "		" });
-		when(accessTypeDef.getImpliedGrants()).thenReturn(impliedGrants);
-		result = _validator.getImpliedGrants(accessTypeDef);
-		assertEquals(4, result.size());
-		
-		// non-empty values get lower cased
-		impliedGrants = Arrays.asList(new String[] { "a", "B", "C	", " d " });
-		when(accessTypeDef.getImpliedGrants()).thenReturn(impliedGrants);
-		result = _validator.getImpliedGrants(accessTypeDef);
-		assertEquals(4, result.size());
-		assertTrue(result.contains("a"));
-		assertTrue(result.contains("b"));
-		assertTrue(result.contains("c	"));
-		assertTrue(result.contains(" d "));
-	}
-	
-	private RangerValidatorForTest _validator;
-	private ServiceStore _store;
-	private ValidationTestUtils _utils = new ValidationTestUtils();
-}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/security-admin/src/test/java/org/apache/ranger/rest/TestServiceRESTForValidation.java
----------------------------------------------------------------------
diff --git a/security-admin/src/test/java/org/apache/ranger/rest/TestServiceRESTForValidation.java b/security-admin/src/test/java/org/apache/ranger/rest/TestServiceRESTForValidation.java
index 5a2ba80..b33cd97 100644
--- a/security-admin/src/test/java/org/apache/ranger/rest/TestServiceRESTForValidation.java
+++ b/security-admin/src/test/java/org/apache/ranger/rest/TestServiceRESTForValidation.java
@@ -38,8 +38,12 @@ import org.apache.ranger.common.RESTErrorUtil;
 import org.apache.ranger.plugin.model.RangerPolicy;
 import org.apache.ranger.plugin.model.RangerService;
 import org.apache.ranger.plugin.model.RangerServiceDef;
+import org.apache.ranger.plugin.model.validation.RangerPolicyValidator;
+import org.apache.ranger.plugin.model.validation.RangerServiceDefValidator;
+import org.apache.ranger.plugin.model.validation.RangerServiceValidator;
+import org.apache.ranger.plugin.model.validation.RangerValidatorFactory;
+import org.apache.ranger.plugin.model.validation.RangerValidator.Action;
 import org.apache.ranger.rest.ServiceREST;
-import org.apache.ranger.rest.RangerValidator.Action;
 import org.junit.Before;
 import org.junit.Test;
 

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/security-admin/src/test/java/org/apache/ranger/rest/ValidationTestUtils.java
----------------------------------------------------------------------
diff --git a/security-admin/src/test/java/org/apache/ranger/rest/ValidationTestUtils.java b/security-admin/src/test/java/org/apache/ranger/rest/ValidationTestUtils.java
deleted file mode 100644
index 3c1c463..0000000
--- a/security-admin/src/test/java/org/apache/ranger/rest/ValidationTestUtils.java
+++ /dev/null
@@ -1,371 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF 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.apache.ranger.rest;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.commons.collections.CollectionUtils;
-import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItem;
-import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemAccess;
-import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
-import org.apache.ranger.plugin.model.RangerServiceDef;
-import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef;
-import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumDef;
-import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumElementDef;
-import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
-import org.apache.ranger.plugin.model.RangerServiceDef.RangerServiceConfigDef;
-import org.apache.ranger.rest.ValidationFailureDetails;
-
-public class ValidationTestUtils {
-	
-	Map<String, String> createMap(String[] keys) {
-		Map<String, String> result = new HashMap<String, String>();
-		for (String key : keys) {
-			result.put(key, "valueof-" + key);
-		}
-		return result;
-	}
-
-	// helper methods for tests
-	List<RangerServiceConfigDef> createServiceConditionDefs(Object[][] input) {
-		List<RangerServiceConfigDef> result = new ArrayList<RangerServiceDef.RangerServiceConfigDef>();
-		
-		for (Object data[] : input) {
-			RangerServiceConfigDef aConfigDef = mock(RangerServiceConfigDef.class);
-			when(aConfigDef.getName()).thenReturn((String)data[0]);
-			when(aConfigDef.getMandatory()).thenReturn((boolean)data[1]);
-			result.add(aConfigDef);
-		}
-		
-		return result;
-	}
-	
-	void checkFailureForSemanticError(List<ValidationFailureDetails> failures, String fieldName) {
-		checkFailure(failures, null, null, true, fieldName, null);
-	}
-
-	void checkFailureForSemanticError(List<ValidationFailureDetails> failures, String fieldName, String subField) {
-		checkFailure(failures, null, null, true, fieldName, subField);
-	}
-
-	void checkFailureForMissingValue(List<ValidationFailureDetails> failures, String field) {
-		checkFailure(failures, null, true, null, field, null);
-	}
-
-	void checkFailureForMissingValue(List<ValidationFailureDetails> failures, String field, String subField) {
-		checkFailure(failures, null, true, null, field, subField);
-	}
-
-	void checkFailureForInternalError(List<ValidationFailureDetails> failures, String fieldName) {
-		checkFailure(failures, true, null, null, fieldName, null);
-	}
-
-	void checkFailureForInternalError(List<ValidationFailureDetails> failures) {
-		checkFailure(failures, true, null, null, null, null);
-	}
-
-	void checkFailure(List<ValidationFailureDetails> failures, Boolean internalError, Boolean missing, Boolean semanticError, String field, String subField) {
-		if (CollectionUtils.isEmpty(failures)) {
-			fail("List of failures is null/empty!");
-		} else {
-			boolean found = false;
-			for (ValidationFailureDetails f : failures) {
-				if ((internalError == null || internalError == f._internalError) &&
-						(missing == null || missing == f._missing) &&
-						(semanticError == null || semanticError == f._semanticError) &&
-						(field == null || field.equals(f._fieldName)) &&
-						(subField == null || subField.equals(f._subFieldName))) {
-					found = true;
-				}
-			}
-			assertTrue(found);
-		}
-	}
-
-	List<RangerAccessTypeDef> createAccessTypeDefs(String[] names) {
-		assertFalse(names == null); // fail if null is passed in!
-		List<RangerAccessTypeDef> defs = new ArrayList<RangerServiceDef.RangerAccessTypeDef>();
-		for (String name : names) {
-			RangerAccessTypeDef def = mock(RangerAccessTypeDef.class);
-			when(def.getName()).thenReturn(name);
-			defs.add(def);
-		}
-		return defs;
-	}
-
-
-	List<RangerAccessTypeDef> createAccessTypeDefs(Object[][] data) {
-		if (data == null) {
-			return null;
-		}
-		List<RangerAccessTypeDef> result = new ArrayList<RangerAccessTypeDef>();
-		if (data.length == 0) {
-			return result;
-		}
-		for (Object[] entry : data) {
-			String accessType = (String)entry[0];
-			String[] impliedAccessArray = (String[])entry[1];
-			List<String> impliedAccesses = null;
-			if (impliedAccessArray != null) {
-				impliedAccesses = Arrays.asList(impliedAccessArray);
-			}
-			RangerAccessTypeDef aTypeDef = mock(RangerAccessTypeDef.class);
-			when(aTypeDef.getName()).thenReturn(accessType);
-			when(aTypeDef.getImpliedGrants()).thenReturn(impliedAccesses);
-			result.add(aTypeDef);
-		}
-		return result;
-	}
-
-	RangerServiceDef createServiceDefWithAccessTypes(String[] accesses) {
-		RangerServiceDef serviceDef = mock(RangerServiceDef.class);
-		List<RangerAccessTypeDef> accessTypeDefs = new ArrayList<RangerServiceDef.RangerAccessTypeDef>();
-		for (String access : accesses) {
-			RangerAccessTypeDef accessTypeDef = mock(RangerAccessTypeDef.class);
-			when(accessTypeDef.getName()).thenReturn(access);
-			accessTypeDefs.add(accessTypeDef);
-		}
-		when(serviceDef.getAccessTypes()).thenReturn(accessTypeDefs);
-		return serviceDef;
-	}
-
-	List<RangerPolicyItemAccess> createItemAccess(Object[][] data) {
-		List<RangerPolicyItemAccess> accesses = new ArrayList<RangerPolicyItemAccess>();
-		for (Object[] row : data) {
-			RangerPolicyItemAccess access = mock(RangerPolicyItemAccess.class);
-			when(access.getType()).thenReturn((String)row[0]);
-			when(access.getIsAllowed()).thenReturn((Boolean)row[1]);
-			accesses.add(access);
-		}
-		return accesses;
-	}
-
-	List<RangerPolicyItem> createPolicyItems(Object[] data) {
-		List<RangerPolicyItem> policyItems = new ArrayList<RangerPolicyItem>();
-		for (Object object : data) {
-			@SuppressWarnings("unchecked")
-			Map<String, Object[]> map = (Map<String, Object[]>) object; 
-			RangerPolicyItem policyItem = mock(RangerPolicyItem.class);
-			
-			List<String> usersList = null;
-			if (map.containsKey("users")) {
-				usersList = Arrays.asList((String[])map.get("users"));
-			}
-			when(policyItem.getUsers()).thenReturn(usersList);
-			
-			List<String> groupsList = null;
-			if (map.containsKey("groups")) {
-				groupsList = Arrays.asList((String[])map.get("groups"));
-			}
-			when(policyItem.getGroups()).thenReturn(groupsList);
-			
-			String[] accesses = (String[])map.get("accesses");;
-			Boolean[] isAllowedFlags = (Boolean[])map.get("isAllowed");
-			List<RangerPolicyItemAccess> accessesList = null;
-			if (accesses != null && isAllowedFlags != null) {
-				accessesList = new ArrayList<RangerPolicyItemAccess>();
-				for (int i = 0; i < accesses.length; i++) {
-					String access = accesses[i];
-					Boolean isAllowed = isAllowedFlags[i]; 
-					RangerPolicyItemAccess itemAccess = mock(RangerPolicyItemAccess.class);
-					when(itemAccess.getType()).thenReturn(access);
-					when(itemAccess.getIsAllowed()).thenReturn(isAllowed);
-					accessesList.add(itemAccess);
-				}
-			}
-			when(policyItem.getAccesses()).thenReturn(accessesList);
-			
-			policyItems.add(policyItem);
-		}
-		return policyItems;
-	}
-
-	List<RangerResourceDef> createResourceDefs(Object[][] data) {
-		// if data itself is null then return null back
-		if (data == null) {
-			return null;
-		}
-		List<RangerResourceDef> defs = new ArrayList<RangerResourceDef>();
-		for (Object[] row : data) {
-			RangerResourceDef aDef = null;
-			if (row != null) {
-				String name = null;
-				Boolean mandatory = null;
-				String regExPattern = null;
-				Boolean isExcludesSupported = null;
-				Boolean isRecursiveSupported = null;
-				switch(row.length) {
-				case 5:
-					isRecursiveSupported = (Boolean)row[4];
-				case 4:
-					isExcludesSupported = (Boolean)row[3];
-				case 3:
-					regExPattern = (String)row[2];
-				case 2:
-					mandatory = (Boolean)row[1];
-				case 1:
-					name = (String)row[0];
-				}
-				aDef = mock(RangerResourceDef.class);
-				when(aDef.getName()).thenReturn(name);
-				when(aDef.getMandatory()).thenReturn(mandatory);
-				when(aDef.getValidationRegEx()).thenReturn(regExPattern);
-				when(aDef.getExcludesSupported()).thenReturn(isExcludesSupported);
-				when(aDef.getRecursiveSupported()).thenReturn(isRecursiveSupported);
-			}
-			defs.add(aDef);
-		}
-		return defs;
-	}
-
-	List<RangerResourceDef> createResourceDefs2(Object[][] data) {
-		// if data itself is null then return null back
-		if (data == null) {
-			return null;
-		}
-		List<RangerResourceDef> defs = new ArrayList<RangerResourceDef>();
-		for (Object[] row : data) {
-			RangerResourceDef aDef = null;
-			if (row != null) {
-				String name = null;
-				Boolean isExcludesSupported = null;
-				Boolean isRecursiveSupported = null;
-				switch(row.length) {
-				case 3:
-					isRecursiveSupported = (Boolean)row[2]; // note: falls through to next case
-				case 2:
-					isExcludesSupported = (Boolean)row[1]; // note: falls through to next case
-				case 1:
-					name = (String)row[0];
-				}
-				aDef = mock(RangerResourceDef.class);
-				when(aDef.getName()).thenReturn(name);
-				when(aDef.getExcludesSupported()).thenReturn(isExcludesSupported);
-				when(aDef.getRecursiveSupported()).thenReturn(isRecursiveSupported);
-			}
-			defs.add(aDef);
-		}
-		return defs;
-	}
-
-	List<RangerResourceDef> createResourceDefsWithRegEx(String[][] data) {
-		// if data itself is null then return null back
-		if (data == null) {
-			return null;
-		}
-		List<RangerResourceDef> defs = new ArrayList<RangerResourceDef>();
-		for (String[] row : data) {
-			RangerResourceDef aDef = null;
-			if (row != null) {
-				String name = row[0];
-				String regEx = row[1];
-				aDef = mock(RangerResourceDef.class);
-				when(aDef.getName()).thenReturn(name);
-				when(aDef.getValidationRegEx()).thenReturn(regEx);
-			}
-			defs.add(aDef);
-		}
-		return defs;
-	}
-
-	Map<String, RangerPolicyResource> createPolicyResourceMap2(Object[][] input) {
-		if (input == null) {
-			return null;
-		}
-		Map<String, RangerPolicyResource> result = new HashMap<String, RangerPolicyResource>(input.length);
-		for (Object[] row : input) {
-			String resourceName = (String)row[0];
-			Boolean isExcludes = (Boolean)row[1];
-			Boolean isRecursive = (Boolean)row[2];
-			RangerPolicyResource aResource = mock(RangerPolicyResource.class);
-			when(aResource.getIsExcludes()).thenReturn(isExcludes);
-			when(aResource.getIsRecursive()).thenReturn(isRecursive);
-			result.put(resourceName, aResource);
-		}
-		return result;
-	}
-
-	List<RangerEnumElementDef> createEnumElementDefs(String[] input) {
-		if (input == null) {
-			return null;
-		}
-		List<RangerEnumElementDef> output = new ArrayList<RangerEnumElementDef>();
-		for (String elementName : input) {
-			RangerEnumElementDef aDef = mock(RangerEnumElementDef.class);
-			when(aDef.getName()).thenReturn(elementName);
-			output.add(aDef);
-		}
-		return output;
-	}
-
-	List<RangerEnumDef> createEnumDefs(Map<String, String[]> input) {
-		if (input == null) {
-			return null;
-		}
-		List<RangerEnumDef> defs = new ArrayList<RangerEnumDef>();
-		for (Map.Entry<String, String[]> entry : input.entrySet()) {
-			RangerEnumDef enumDef = mock(RangerEnumDef.class);
-			String enumName = entry.getKey();
-			if ("null".equals(enumName)) { // special handling to process null hint in enum-name
-				enumName = null;
-			}
-			when(enumDef.getName()).thenReturn(enumName);
-			List<RangerEnumElementDef> elements = createEnumElementDefs(entry.getValue());
-			when(enumDef.getElements()).thenReturn(elements);
-			// by default set default index to last element
-			when(enumDef.getDefaultIndex()).thenReturn(elements.size() - 1);
-			defs.add(enumDef);
-		}
-		return defs;
-	}
-
-	Map<String, RangerPolicyResource> createPolicyResourceMap(Object[][] input) {
-		if (input == null) {
-			return null;
-		}
-		Map<String, RangerPolicyResource> result = new HashMap<String, RangerPolicyResource>(input.length);
-		for (Object[] row : input) {
-			String resourceName = (String)row[0];
-			String[] valuesArray = (String[])row[1];
-			Boolean isExcludes = (Boolean)row[2];
-			Boolean isRecursive = (Boolean)row[3];
-			RangerPolicyResource aResource = mock(RangerPolicyResource.class);
-			if (valuesArray == null) {
-				when(aResource.getValues()).thenReturn(null);
-			} else {
-				when(aResource.getValues()).thenReturn(Arrays.asList(valuesArray));
-			}
-			when(aResource.getIsExcludes()).thenReturn(isExcludes);
-			when(aResource.getIsRecursive()).thenReturn(isRecursive);
-			result.put(resourceName, aResource);
-		}
-		return result;
-	}
-}


[2/4] incubator-ranger git commit: RANGER-278 move validation classes under org.apache.ranger.plugin.model.validation

Posted by ma...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/security-admin/src/main/java/org/apache/ranger/rest/RangerPolicyValidator.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/rest/RangerPolicyValidator.java b/security-admin/src/main/java/org/apache/ranger/rest/RangerPolicyValidator.java
deleted file mode 100644
index 21d14e2..0000000
--- a/security-admin/src/main/java/org/apache/ranger/rest/RangerPolicyValidator.java
+++ /dev/null
@@ -1,496 +0,0 @@
-package org.apache.ranger.rest;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.commons.collections.CollectionUtils;
-import org.apache.commons.lang.StringUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.ranger.plugin.model.RangerPolicy;
-import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItem;
-import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemAccess;
-import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
-import org.apache.ranger.plugin.model.RangerService;
-import org.apache.ranger.plugin.model.RangerServiceDef;
-import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
-import org.apache.ranger.plugin.store.ServiceStore;
-
-import com.google.common.collect.Sets;
-
-public class RangerPolicyValidator extends RangerValidator {
-
-	private static final Log LOG = LogFactory.getLog(RangerPolicyValidator.class);
-
-	public RangerPolicyValidator(ServiceStore store) {
-		super(store);
-	}
-
-	public void validate(RangerPolicy policy, Action action) throws Exception {
-		if(LOG.isDebugEnabled()) {
-			LOG.debug(String.format("==> RangerPolicyValidator.validate(%s, %s)", policy, action));
-		}
-
-		List<ValidationFailureDetails> failures = new ArrayList<ValidationFailureDetails>();
-		boolean valid = isValid(policy, action, failures);
-		String message = "";
-		try {
-			if (!valid) {
-				message = serializeFailures(failures);
-				throw new Exception(message);
-			}
-		} finally {
-			if(LOG.isDebugEnabled()) {
-				LOG.debug(String.format("<== RangerPolicyValidator.validate(%s, %s): %s, reason[%s]", policy, action, valid, message));
-			}
-		}
-	}
-
-	@Override
-	boolean isValid(Long id, Action action, List<ValidationFailureDetails> failures) {
-		if(LOG.isDebugEnabled()) {
-			LOG.debug(String.format("==> RangerPolicyValidator.isValid(%s, %s, %s)", id, action, failures));
-		}
-
-		boolean valid = true;
-		if (action != Action.DELETE) {
-			failures.add(new ValidationFailureDetailsBuilder()
-				.isAnInternalError()
-				.becauseOf("isValid(Long) is only supported for DELETE")
-				.build());
-			valid = false;
-		} else if (id == null) {
-			failures.add(new ValidationFailureDetailsBuilder()
-				.field("id")
-				.isMissing()
-				.build());
-			valid = false;
-		} else if (getPolicy(id) == null) {
-			failures.add(new ValidationFailureDetailsBuilder()
-				.field("id")
-				.isSemanticallyIncorrect()
-				.becauseOf("no policy found for id[" + id + "]")
-				.build());
-			valid = false;
-		}
-
-		if(LOG.isDebugEnabled()) {
-			LOG.debug(String.format("<== RangerPolicyValidator.isValid(%s, %s, %s): %s", id, action, failures, valid));
-		}
-		return valid;
-	}
-
-	boolean isValid(RangerPolicy policy, Action action, List<ValidationFailureDetails> failures) {
-		if(LOG.isDebugEnabled()) {
-			LOG.debug(String.format("==> RangerPolicyValidator.isValid(%s, %s, %s)", policy, action, failures));
-		}
-
-		if (!(action == Action.CREATE || action == Action.UPDATE)) {
-			throw new IllegalArgumentException("isValid(RangerPolicy, ...) is only supported for create/update");
-		}
-		boolean valid = true;
-		if (policy == null) {
-			String message = "policy object passed in was null";
-			LOG.debug(message);
-			failures.add(new ValidationFailureDetailsBuilder()
-				.field("policy")
-				.isMissing()
-				.becauseOf(message)
-				.build());
-			valid = false;
-		} else {
-			Long id = policy.getId();
-			if (action == Action.UPDATE) { // id is ignored for CREATE
-				if (id == null) {
-					String message = "policy id was null/empty/blank"; 
-					LOG.debug(message);
-					failures.add(new ValidationFailureDetailsBuilder()
-						.field("id")
-						.isMissing()
-						.becauseOf(message)
-						.build());
-					valid = false;
-				} else if (getPolicy(id) == null) {
-					failures.add(new ValidationFailureDetailsBuilder()
-						.field("id")
-						.isSemanticallyIncorrect()
-						.becauseOf("no policy exists with id[" + id +"]")
-						.build());
-					valid = false;
-				}
-			}
-			String policyName = policy.getName();
-			String serviceName = policy.getService();
-			if (StringUtils.isBlank(policyName)) {
-				String message = "policy name was null/empty/blank[" + policyName + "]"; 
-				LOG.debug(message);
-				failures.add(new ValidationFailureDetailsBuilder()
-					.field("name")
-					.isMissing()
-					.becauseOf(message)
-					.build());
-				valid = false;
-			} else {
-				List<RangerPolicy> policies = getPolicies(policyName, serviceName);
-				if (CollectionUtils.isNotEmpty(policies)) {
-					if (policies.size() > 1) {
-						failures.add(new ValidationFailureDetailsBuilder()
-							.isAnInternalError()
-							.becauseOf("multiple policies found with the name[" + policyName + "]")
-							.build());
-						valid = false;
-					} else if (action == Action.CREATE) { // size == 1
-						failures.add(new ValidationFailureDetailsBuilder()
-							.field("name")
-							.isSemanticallyIncorrect()
-							.becauseOf("policy already exists with name[" + policyName + "]; its id is[" + policies.iterator().next().getId() + "]")
-							.build());
-						valid = false;
-					} else if (policies.iterator().next().getId() != id) { // size == 1 && action == UPDATE
-						failures.add(new ValidationFailureDetailsBuilder()
-							.field("id/name")
-							.isSemanticallyIncorrect()
-							.becauseOf("id/name conflict: another policy already exists with name[" + policyName + "], its id is[" + policies.iterator().next().getId() + "]")
-							.build());
-						valid = false;
-					}
-				}
-			}
-			RangerService service = null;
-			if (StringUtils.isBlank(serviceName)) {
-				failures.add(new ValidationFailureDetailsBuilder()
-				.field("service")
-				.isMissing()
-				.becauseOf("service name was null/empty/blank")
-				.build());
-				valid = false;
-			} else {
-				service = getService(serviceName);
-				if (service == null) {
-					failures.add(new ValidationFailureDetailsBuilder()
-						.field("service")
-						.isMissing()
-						.becauseOf("service name was null/empty/blank")
-						.build());
-					valid = false;
-				}
-			}
-			List<RangerPolicyItem> policyItems = policy.getPolicyItems();
-			boolean isAuditEnabled = getIsAuditEnabled(policy);
-			RangerServiceDef serviceDef = null;
-			String serviceDefName = null;
-			if (CollectionUtils.isEmpty(policyItems) && !isAuditEnabled) {
-				failures.add(new ValidationFailureDetailsBuilder()
-					.field("policy items")
-					.isMissing()
-					.becauseOf("at least one policy item must be specified if audit isn't enabled")
-					.build());
-				valid = false;
-			} else if (service != null) {
-				serviceDefName = service.getType();
-				serviceDef = getServiceDef(serviceDefName);
-				if (serviceDef == null) {
-					failures.add(new ValidationFailureDetailsBuilder()
-						.field("policy service def")
-						.isAnInternalError()
-						.becauseOf("Service def of policies service does not exist")
-						.build());
-					valid = false;
-				} else {
-					valid = isValidPolicyItems(policyItems, failures, serviceDef) && valid;
-				}
-			}
-			if (serviceDef != null) {
-				Set<String> mandatoryResources = getMandatoryResourceNames(serviceDef);
-				Set<String> policyResources = getPolicyResources(policy);
-				Set<String> missingResources = Sets.difference(mandatoryResources, policyResources);
-				if (!missingResources.isEmpty()) {
-					failures.add(new ValidationFailureDetailsBuilder()
-						.field("resources")
-						.subField(missingResources.iterator().next()) // we return any one parameter!
-						.isMissing()
-						.becauseOf("required resources[" + missingResources + "] are missing")
-						.build());
-					valid = false;
-				}
-				Set<String> allResource = getAllResourceNames(serviceDef);
-				Set<String> unknownResources = Sets.difference(policyResources, allResource);
-				if (!unknownResources.isEmpty()) {
-					failures.add(new ValidationFailureDetailsBuilder()
-						.field("resources")
-						.subField(unknownResources.iterator().next()) // we return any one parameter!
-						.isSemanticallyIncorrect()
-						.becauseOf("resource[" + unknownResources + "] is not valid for service-def[" + serviceDefName + "]")
-						.build());
-					valid = false;
-				}
-				Map<String, RangerPolicyResource> resourceMap = policy.getResources();
-				valid = isValidResourceValues(resourceMap, failures, serviceDef) && valid;
-				valid = isValidResourceFlags(resourceMap, failures, serviceDef.getResources(), serviceDefName, policyName) && valid;
-			}
-		}
-		
-		if(LOG.isDebugEnabled()) {
-			LOG.debug(String.format("<== RangerPolicyValidator.isValid(%s, %s, %s): %s", policy, action, failures, valid));
-		}
-		return valid;
-	}
-	
-	boolean isValidResourceFlags(final Map<String, RangerPolicyResource> inputPolicyResources, final List<ValidationFailureDetails> failures,
-			final List<RangerResourceDef> resourceDefs, final String serviceDefName, final String policyName) {
-		if(LOG.isDebugEnabled()) {
-			LOG.debug(String.format("==> RangerPolicyValidator.isValidResourceFlags(%s, %s, %s, %s, %s)", inputPolicyResources, failures, resourceDefs, serviceDefName, policyName));
-		}
-
-		boolean valid = true;
-		if (inputPolicyResources == null) {
-			LOG.debug("isValidResourceFlags: resourceMap is null");
-		} else if (resourceDefs == null) {
-			LOG.debug("isValidResourceFlags: service Def is null");
-		} else {
-			Map<String, RangerPolicyResource> policyResources = getPolicyResourceWithLowerCaseKeys(inputPolicyResources);
-			for (RangerResourceDef resourceDef : resourceDefs) {
-				if (resourceDef == null) {
-					failures.add(new ValidationFailureDetailsBuilder()
-						.field("resource-def")
-						.isAnInternalError()
-						.becauseOf("a resource-def on resource def collection of service-def[" + serviceDefName + "] was null")
-						.build());
-					valid = false;
-				} else if (StringUtils.isBlank(resourceDef.getName())) {
-					failures.add(new ValidationFailureDetailsBuilder()
-						.field("resource-def-name")
-						.isAnInternalError()
-						.becauseOf("name of a resource-def on resource def collection of service-def[" + serviceDefName + "] was null")
-						.build());
-					valid = false;
-				} else {
-					String resourceName = resourceDef.getName().toLowerCase();
-					RangerPolicyResource policyResource = policyResources.get(resourceName);
-					if (policyResource == null) {
-						if (LOG.isDebugEnabled()) {
-							LOG.debug("a policy-resource object for resource[" + resourceName + "] on policy [" + policyName + "] was null");
-						}
-					} else {
-						boolean excludesSupported = Boolean.TRUE.equals(resourceDef.getExcludesSupported()); // could be null
-						boolean policyIsExcludes = Boolean.TRUE.equals(policyResource.getIsExcludes()); // could be null
-						if (policyIsExcludes && !excludesSupported) {
-							failures.add(new ValidationFailureDetailsBuilder()
-								.field("isExcludes")
-								.subField(resourceName)
-								.isSemanticallyIncorrect()
-								.becauseOf("isExcludes specified as [" + policyIsExcludes + "] for resource [" + resourceName + "] which doesn't support isExcludes")
-								.build());
-							valid = false;
-						}
-						boolean recursiveSupported = Boolean.TRUE.equals(resourceDef.getRecursiveSupported());
-						boolean policyIsRecursive = Boolean.TRUE.equals(policyResource.getIsRecursive());
-						if (policyIsRecursive && !recursiveSupported) {
-							failures.add(new ValidationFailureDetailsBuilder()
-								.field("isRecursive")
-								.subField(resourceName)
-								.isSemanticallyIncorrect()
-								.becauseOf("isRecursive specified as [" + policyIsRecursive + "] for resource [" + resourceName + "] which doesn't support isRecursive")
-								.build());
-							valid = false;
-						}
-					}
-				}
-			}
-		}
-
-		if(LOG.isDebugEnabled()) {
-			LOG.debug(String.format("<== RangerPolicyValidator.isValidResourceFlags(%s, %s, %s, %s, %s): %s", inputPolicyResources, failures, resourceDefs, serviceDefName, policyName, valid));
-		}
-		return valid;
-	}
-
-	boolean isValidResourceValues(Map<String, RangerPolicyResource> resourceMap, List<ValidationFailureDetails> failures, RangerServiceDef serviceDef) {
-		if(LOG.isDebugEnabled()) {
-			LOG.debug(String.format("==> RangerPolicyValidator.isValidResourceValues(%s, %s, %s)", resourceMap, failures, serviceDef));
-		}
-
-		boolean valid = true;
-		if (resourceMap == null) {
-			LOG.debug("isValidResourceValues: resourceMap is null");
-		} else if (serviceDef == null) {
-			LOG.debug("isValidResourceValues: service Def is null");
-		} else {
-			Map<String, String> validationRegExMap = getValidationRegExes(serviceDef);
-			for (Map.Entry<String, RangerPolicyResource> entry : resourceMap.entrySet()) {
-				String name = entry.getKey();
-				RangerPolicyResource policyResource = entry.getValue();
-				if (validationRegExMap.containsKey(name) && policyResource != null && CollectionUtils.isNotEmpty(policyResource.getValues())) {
-					String regEx = validationRegExMap.get(name);
-					for (String aValue : policyResource.getValues()) {
-						if (StringUtils.isBlank(aValue)) {
-							LOG.debug("resource value was blank");
-						} else if (!aValue.matches(regEx)) {
-							failures.add(new ValidationFailureDetailsBuilder()
-								.field("resource-values")
-								.subField(name)
-								.isSemanticallyIncorrect()
-								.becauseOf("resources value[" + aValue + "] does not match validation regex[" + regEx + "] defined on service-def[" + serviceDef.getName() + "]")
-								.build());
-							valid = false;
-						}
-					}
-				}
-			}
-		}
-
-		if(LOG.isDebugEnabled()) {
-			LOG.debug(String.format("<== RangerPolicyValidator.isValidResourceValues(%s, %s, %s): %s", resourceMap, failures, serviceDef, valid));
-		}
-		return valid;
-	}
-
-	boolean isValidPolicyItems(List<RangerPolicyItem> policyItems, List<ValidationFailureDetails> failures, RangerServiceDef serviceDef) {
-		if(LOG.isDebugEnabled()) {
-			LOG.debug(String.format("==> RangerPolicyValidator.isValid(%s, %s, %s)", policyItems, failures, serviceDef));
-		}
-
-		boolean valid = true;
-		if (CollectionUtils.isEmpty(policyItems)) {
-			LOG.debug("policy items collection was null/empty");
-		} else {
-			for (RangerPolicyItem policyItem : policyItems) {
-				if (policyItem == null) {
-					failures.add(new ValidationFailureDetailsBuilder()
-						.field("policy item")
-						.isMissing()
-						.becauseOf("policy items object was null")
-						.build());
-					valid = false;
-				} else {
-					// we want to go through all elements even though one may be bad so all failures are captured
-					valid = isValidPolicyItem(policyItem, failures, serviceDef) && valid;
-				}
-			}
-		}
-
-		if(LOG.isDebugEnabled()) {
-			LOG.debug(String.format("<== RangerPolicyValidator.isValid(%s, %s, %s): %s", policyItems, failures, serviceDef, valid));
-		}
-		return valid;
-	}
-
-	boolean isValidPolicyItem(RangerPolicyItem policyItem, List<ValidationFailureDetails> failures, RangerServiceDef serviceDef) {
-		if(LOG.isDebugEnabled()) {
-			LOG.debug(String.format("==> RangerPolicyValidator.isValid(%s, %s, %s)", policyItem, failures, serviceDef));
-		}
-		
-		boolean valid = true;
-		if (policyItem == null) {
-			LOG.debug("policy item was null!");
-		} else {
-			// access items collection can't be empty and should be otherwise valid
-			if (CollectionUtils.isEmpty(policyItem.getAccesses())) {
-				failures.add(new ValidationFailureDetailsBuilder()
-					.field("policy item accesses")
-					.isMissing()
-					.becauseOf("policy items accesses collection was null")
-					.build());
-				valid = false;
-			} else {
-				valid = isValidItemAccesses(policyItem.getAccesses(), failures, serviceDef) && valid;
-			}
-			// both users and user-groups collections can't be empty
-			if (CollectionUtils.isEmpty(policyItem.getUsers()) && CollectionUtils.isEmpty(policyItem.getGroups())) {
-				failures.add(new ValidationFailureDetailsBuilder()
-					.field("policy item users/user-groups")
-					.isMissing()
-					.becauseOf("both users and user-groups collections on the policy item were null/empty")
-					.build());
-				valid = false;
-			}
-		}
-
-		if(LOG.isDebugEnabled()) {
-			LOG.debug(String.format("<== RangerPolicyValidator.isValid(%s, %s, %s): %s", policyItem, failures, serviceDef, valid));
-		}
-		return valid;
-	}
-
-	boolean isValidItemAccesses(List<RangerPolicyItemAccess> accesses, List<ValidationFailureDetails> failures, RangerServiceDef serviceDef) {
-		if(LOG.isDebugEnabled()) {
-			LOG.debug(String.format("==> RangerPolicyValidator.isValid(%s, %s, %s)", accesses, failures, serviceDef));
-		}
-		
-		boolean valid = true;
-		if (CollectionUtils.isEmpty(accesses)) {
-			LOG.debug("policy item accesses collection was null/empty!");
-		} else {
-			Set<String> accessTypes = getAccessTypes(serviceDef);
-			for (RangerPolicyItemAccess access : accesses) {
-				if (access == null) {
-					failures.add(new ValidationFailureDetailsBuilder()
-						.field("policy item access")
-						.isMissing()
-						.becauseOf("policy items access object was null")
-						.build());
-					valid = false;
-				} else {
-					// we want to go through all elements even though one may be bad so all failures are captured
-					valid = isValidPolicyItemAccess(access, failures, accessTypes) && valid;
-				}
-			}
-		}
-
-		if(LOG.isDebugEnabled()) {
-			LOG.debug(String.format("<== RangerPolicyValidator.isValid(%s, %s): %s", accesses, failures, serviceDef, valid));
-		}
-		return valid;
-	}
-
-	boolean isValidPolicyItemAccess(RangerPolicyItemAccess access, List<ValidationFailureDetails> failures, Set<String> accessTypes) {
-		if(LOG.isDebugEnabled()) {
-			LOG.debug(String.format("==> RangerPolicyValidator.isValidPolicyItemAccess(%s, %s, %s)", access, failures, accessTypes));
-		}
-		
-		boolean valid = true;
-		if (CollectionUtils.isEmpty(accessTypes)) { // caller should firewall this argument!
-			LOG.debug("isValidPolicyItemAccess: accessTypes was null!");
-		} else if (access == null) {
-			LOG.debug("isValidPolicyItemAccess: policy item access was null!");
-		} else {
-			String accessType = access.getType();
-			if (StringUtils.isBlank(accessType)) {
-				failures.add(new ValidationFailureDetailsBuilder()
-					.field("policy item access type")
-					.isMissing()
-					.becauseOf("policy items access type's name was null/empty/blank")
-					.build());
-				valid = false;
-			} else if (!accessTypes.contains(accessType.toLowerCase())) {
-				String message = String.format("access type[%s] not among valid types for service[%s]", accessType, accessTypes);
-				LOG.debug(message);
-				failures.add(new ValidationFailureDetailsBuilder()
-					.field("policy item access type")
-					.isSemanticallyIncorrect()
-					.becauseOf(message)
-					.build());
-				valid = false;
-			}
-			Boolean isAllowed = access.getIsAllowed();
-			// it can be null (which is treated as allowed) but not false
-			if (isAllowed != null && isAllowed == false) {
-				String message = "access type is set to deny.  Currently deny access types are not supported.";
-				LOG.debug(message);
-				failures.add(new ValidationFailureDetailsBuilder()
-					.field("policy item access type allowed")
-					.isSemanticallyIncorrect()
-					.becauseOf(message)
-					.build());
-				valid = false;
-			}
-		}
-		
-		if(LOG.isDebugEnabled()) {
-			LOG.debug(String.format("<== RangerPolicyValidator.isValidPolicyItemAccess(%s, %s, %s): %s", access, failures, accessTypes, valid));
-		}
-		return valid;
-	}
-}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/security-admin/src/main/java/org/apache/ranger/rest/RangerServiceDefValidator.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/rest/RangerServiceDefValidator.java b/security-admin/src/main/java/org/apache/ranger/rest/RangerServiceDefValidator.java
deleted file mode 100644
index a84f68a..0000000
--- a/security-admin/src/main/java/org/apache/ranger/rest/RangerServiceDefValidator.java
+++ /dev/null
@@ -1,365 +0,0 @@
-package org.apache.ranger.rest;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import org.apache.commons.collections.CollectionUtils;
-import org.apache.commons.lang.StringUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.ranger.plugin.model.RangerServiceDef;
-import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef;
-import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumDef;
-import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumElementDef;
-import org.apache.ranger.plugin.store.ServiceStore;
-
-import com.google.common.collect.Sets;
-
-public class RangerServiceDefValidator extends RangerValidator {
-
-	private static final Log LOG = LogFactory.getLog(RangerServiceDefValidator.class);
-
-	public RangerServiceDefValidator(ServiceStore store) {
-		super(store);
-	}
-
-	public void validate(final RangerServiceDef serviceDef, final Action action) throws Exception {
-		if(LOG.isDebugEnabled()) {
-			LOG.debug(String.format("==> RangerServiceDefValidator.validate(%s, %s)", serviceDef, action));
-		}
-
-		List<ValidationFailureDetails> failures = new ArrayList<ValidationFailureDetails>();
-		boolean valid = isValid(serviceDef, action, failures);
-		String message = "";
-		try {
-			if (!valid) {
-				message = serializeFailures(failures);
-				throw new Exception(message);
-			}
-		} finally {
-			if(LOG.isDebugEnabled()) {
-				LOG.debug(String.format("<== RangerServiceDefValidator.validate(%s, %s): %s, reason[%s]", serviceDef, action, valid, message));
-			}
-		}
-	}
-
-	boolean isValid(final Long id, final Action action, final List<ValidationFailureDetails> failures) {
-		if(LOG.isDebugEnabled()) {
-			LOG.debug("==> RangerServiceDefValidator.isValid(" + id + ")");
-		}
-
-		boolean valid = true;
-		if (action != Action.DELETE) {
-			failures.add(new ValidationFailureDetailsBuilder()
-				.isAnInternalError()
-				.becauseOf("unsupported action[" + action + "]; isValid(Long) is only supported for DELETE")
-				.build());
-			valid = false;
-		} else if (id == null) {
-			failures.add(new ValidationFailureDetailsBuilder()
-				.field("id")
-				.isMissing()
-				.build());
-			valid = false;
-		} else if (getServiceDef(id) == null) {
-			failures.add(new ValidationFailureDetailsBuilder()
-				.field("id")
-				.isSemanticallyIncorrect()
-				.becauseOf("no service def found for id[" + id + "]")
-				.build());
-			valid = false;
-		}
-
-		if(LOG.isDebugEnabled()) {
-			LOG.debug("<== RangerServiceDefValidator.isValid(" + id + "): " + valid);
-		}
-		return valid;
-	}
-	
-	boolean isValid(final RangerServiceDef serviceDef, final Action action, final List<ValidationFailureDetails> failures) {
-		if(LOG.isDebugEnabled()) {
-			LOG.debug("==> RangerServiceDefValidator.isValid(" + serviceDef + ")");
-		}
-		
-		if (!(action == Action.CREATE || action == Action.UPDATE)) {
-			throw new IllegalArgumentException("isValid(RangerServiceDef, ...) is only supported for CREATE/UPDATE");
-		}
-		boolean valid = true;
-		if (serviceDef == null) {
-			String message = "service def object passed in was null";
-			LOG.debug(message);
-			failures.add(new ValidationFailureDetailsBuilder()
-				.field("service def")
-				.isMissing()
-				.becauseOf(message)
-				.build());
-			valid = false;
-		} else {
-			Long id = serviceDef.getId();
-			if (action == Action.UPDATE) { // id is ignored for CREATE
-				if (id == null) {
-					String message = "service def id was null/empty/blank"; 
-					LOG.debug(message);
-					failures.add(new ValidationFailureDetailsBuilder()
-						.field("id")
-						.isMissing()
-						.becauseOf(message)
-						.build());
-					valid = false;
-				} else if (getServiceDef(id) == null) {
-					failures.add(new ValidationFailureDetailsBuilder()
-						.field("id")
-						.isSemanticallyIncorrect()
-						.becauseOf("no service def exists with id[" + id +"]")
-						.build());
-					valid = false;
-				}
-			}
-			// validate the service def name
-			String name = serviceDef.getName();
-			boolean nameSpecified = StringUtils.isNotBlank(name);
-			if (!nameSpecified) {
-				String message = "service def name[" + name + "] was null/empty/blank"; 
-				LOG.debug(message);
-				failures.add(new ValidationFailureDetailsBuilder()
-					.field("name")
-					.isMissing()
-					.becauseOf(message)
-					.build());
-				valid = false;
-			} else {
-				RangerServiceDef otherServiceDef = getServiceDef(name);
-				if (otherServiceDef != null && action == Action.CREATE) {
-					failures.add(new ValidationFailureDetailsBuilder()
-						.field("name")
-						.isSemanticallyIncorrect()
-						.becauseOf("service def with the name[" + name + "] already exists")
-						.build());
-					valid = false;
-				} else if (otherServiceDef != null && otherServiceDef.getId() !=null && otherServiceDef.getId() != id) {
-					failures.add(new ValidationFailureDetailsBuilder()
-						.field("id/name")
-						.isSemanticallyIncorrect()
-						.becauseOf("id/name conflict: another service def already exists with name[" + name + "], its id is [" + otherServiceDef.getId() + "]")
-						.build());
-					valid = false;
-				}
-			}
-			if (CollectionUtils.isEmpty(serviceDef.getAccessTypes())) {
-				failures.add(new ValidationFailureDetailsBuilder()
-					.field("access types")
-					.isMissing()
-					.becauseOf("access types collection was null/empty")
-					.build());
-				valid = false;
-			} else {
-				valid = isValidAccessTypes(serviceDef.getAccessTypes(), failures) && valid;
-			}
-			if (CollectionUtils.isEmpty(serviceDef.getEnums())) {
-				LOG.debug("No enums specified on the service def.  Ok!");
-			} else {
-				valid = isValidEnums(serviceDef.getEnums(), failures) && valid;
-			}
-		}
-		
-		if(LOG.isDebugEnabled()) {
-			LOG.debug("<== RangerServiceDefValidator.isValid(" + serviceDef + "): " + valid);
-		}
-		return valid;
-	}
-
-	boolean isValidAccessTypes(final List<RangerAccessTypeDef> accessTypeDefs, final List<ValidationFailureDetails> failures) {
-		if(LOG.isDebugEnabled()) {
-			LOG.debug(String.format("==> RangerServiceDefValidator.isValidAccessTypes(%s, %s)", accessTypeDefs, failures));
-		}
-		
-		boolean valid = true;
-		if (CollectionUtils.isEmpty(accessTypeDefs)) {
-			LOG.debug("access type def collection is empty/null");
-		} else {
-			List<RangerAccessTypeDef> defsWithImpliedGrants = new ArrayList<RangerAccessTypeDef>();
-			Set<String> accessNames = new HashSet<String>();
-			for (RangerAccessTypeDef def : accessTypeDefs) {
-				String name = def.getName();
-				// name can't be null/empty/blank
-				if (StringUtils.isBlank(name)) {
-					failures.add(new ValidationFailureDetailsBuilder()
-						.field("access type name")
-						.isMissing()
-						.becauseOf("access type name[" + name + "] is null/empty")
-						.build());
-					valid = false;
-				} else if (accessNames.contains(name.toLowerCase())) {
-					failures.add(new ValidationFailureDetailsBuilder()
-						.field("access type name")
-						.subField(name)
-						.isSemanticallyIncorrect()
-						.becauseOf("duplicate access type names in access types collection: [" + name + "]")
-						.build());
-					valid = false;
-				} else {
-					accessNames.add(name.toLowerCase()); // we have a new unique access type
-				}
-				if (CollectionUtils.isNotEmpty(def.getImpliedGrants())) {
-					defsWithImpliedGrants.add(def);
-				}
-			}
-			// validate implied grants
-			for (RangerAccessTypeDef def : defsWithImpliedGrants) {
-				Collection<String> impliedGrants = getImpliedGrants(def);
-				Set<String> unknownAccessTypes = Sets.difference(Sets.newHashSet(impliedGrants), accessNames);
-				if (!unknownAccessTypes.isEmpty()) {
-					failures.add(new ValidationFailureDetailsBuilder()
-						.field("implied grants")
-						.subField(unknownAccessTypes.iterator().next())  // we return just on item here.  Message has all unknow items
-						.isSemanticallyIncorrect()
-						.becauseOf("implied grant[" + impliedGrants + "] contains an unknown access types[" + unknownAccessTypes + "]")
-						.build());
-					valid = false;
-				}
-				// implied grant should not imply itself! 
-				String name = def.getName(); // note: this name could be null/blank/empty!
-				if (impliedGrants.contains(name)) {
-					failures.add(new ValidationFailureDetailsBuilder()
-						.field("implied grants")
-						.subField(name)
-						.isSemanticallyIncorrect()
-						.becauseOf("implied grants list [" + impliedGrants + "] for access type[" + name + "] contains itself")
-						.build());
-					valid = false;
-				}
-			}
-		}
-		
-		if(LOG.isDebugEnabled()) {
-			LOG.debug(String.format("<== RangerServiceDefValidator.isValidAccessTypes(%s, %s): %s", accessTypeDefs, failures, valid));
-		}
-		return valid;
-	}
-
-	boolean isValidEnums(List<RangerEnumDef> enumDefs, List<ValidationFailureDetails> failures) {
-		if(LOG.isDebugEnabled()) {
-			LOG.debug(String.format("==> RangerServiceDefValidator.isValidEnums(%s, %s)", enumDefs, failures));
-		}
-		
-		boolean valid = true;
-		if (CollectionUtils.isEmpty(enumDefs)) {
-			LOG.debug("enum def collection passed in was null/empty");
-		} else {
-			Set<String> enumNames = new HashSet<String>();
-			for (RangerEnumDef enumDef : enumDefs) {
-				if (enumDef == null) {
-					failures.add(new ValidationFailureDetailsBuilder()
-						.field("enum def")
-						.isMissing()
-						.becauseOf("An enum def in enums collection is null")
-						.build());
-					valid = false;
-				} else {
-					// enum-names must non-blank and be unique to a service definition
-					String enumName = enumDef.getName();
-					if (StringUtils.isBlank(enumName)) {
-						failures.add(new ValidationFailureDetailsBuilder()
-							.field("enum def name")
-							.isMissing()
-							.becauseOf("enum name [" + enumName + "] is null/empty")
-							.build());
-						valid = false;
-					} else if (enumNames.contains(enumName.toLowerCase())) {
-						failures.add(new ValidationFailureDetailsBuilder()
-							.field("enum def name")
-							.subField(enumName)
-							.isSemanticallyIncorrect()
-							.becauseOf("dumplicate enum name [" + enumName + "] found")
-							.build());
-						valid = false;
-					} else {
-						enumNames.add(enumName.toLowerCase());
-					}
-					// enum must contain at least one valid value and those values should be non-blank and distinct
-					if (CollectionUtils.isEmpty(enumDef.getElements())) {
-						failures.add(new ValidationFailureDetailsBuilder()
-							.field("enum values")
-							.subField(enumName)
-							.isMissing()
-							.becauseOf("enum [" + enumName + "] does not have any elements")
-							.build());
-						valid = false;
-					} else {
-						valid = isValidEnumElements(enumDef.getElements(), failures, enumName) && valid;
-						// default index should be valid
-						int defaultIndex = getEnumDefaultIndex(enumDef);
-						if (defaultIndex < 0 || defaultIndex >= enumDef.getElements().size()) { // max index is one less than the size of the elements list
-							failures.add(new ValidationFailureDetailsBuilder()
-								.field("enum default index")
-								.subField(enumName)
-								.isSemanticallyIncorrect()
-								.becauseOf("default index[" + defaultIndex + "] for enum [" + enumName + "] is invalid")
-								.build());
-							valid = false;
-						}
-					}
-				}
-			}
-		}
-		
-		if(LOG.isDebugEnabled()) {
-			LOG.debug(String.format("<== RangerServiceDefValidator.isValidEnums(%s, %s): %s", enumDefs, failures, valid));
-		}
-		return valid;
-	}
-
-	boolean isValidEnumElements(List<RangerEnumElementDef> enumElementsDefs, List<ValidationFailureDetails> failures, String enumName) {
-		if(LOG.isDebugEnabled()) {
-			LOG.debug(String.format("==> RangerServiceDefValidator.isValidEnums(%s, %s)", enumElementsDefs, failures));
-		}
-		
-		boolean valid = true;
-		if (CollectionUtils.isEmpty(enumElementsDefs)) {
-			LOG.debug("Enum elements list passed in was null/empty!");
-		} else {
-			// enum element names should be valid and distinct
-			Set<String> elementNames = new HashSet<String>();
-			for (RangerEnumElementDef elementDef : enumElementsDefs) {
-				if (elementDef == null) {
-					failures.add(new ValidationFailureDetailsBuilder()
-						.field("enum element")
-						.subField(enumName)
-						.isMissing()
-						.becauseOf("An enum element in enum element collection of enum [" + enumName + "] is null")
-						.build());
-					valid = false;
-				} else {
-					String elementName = elementDef.getName();
-					if (StringUtils.isBlank(elementName)) {
-						failures.add(new ValidationFailureDetailsBuilder()
-							.field("enum element name")
-							.subField(enumName)
-							.isMissing()
-							.becauseOf("Name of an element of enum [" + enumName + "] is null/empty[" + elementName + "]")
-							.build());
-						valid = false;
-					} else if (elementNames.contains(elementName.toLowerCase())) {
-						failures.add(new ValidationFailureDetailsBuilder()
-							.field("enum element name")
-							.subField(enumName)
-							.isSemanticallyIncorrect()
-							.becauseOf("dumplicate enum element name [" + elementName + "] found for enum[" + enumName + "]")
-							.build());
-						valid = false;
-					} else {
-						elementNames.add(elementName.toLowerCase());
-					}
-				}
-			}
-		}
-		
-		if(LOG.isDebugEnabled()) {
-			LOG.debug(String.format("<== RangerServiceDefValidator.isValidEnums(%s, %s): %s", enumElementsDefs, failures, valid));
-		}
-		return valid;
-	}
-}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/security-admin/src/main/java/org/apache/ranger/rest/RangerServiceValidator.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/rest/RangerServiceValidator.java b/security-admin/src/main/java/org/apache/ranger/rest/RangerServiceValidator.java
deleted file mode 100644
index 3a55638..0000000
--- a/security-admin/src/main/java/org/apache/ranger/rest/RangerServiceValidator.java
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF 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.apache.ranger.rest;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-
-import org.apache.commons.lang.StringUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.ranger.plugin.model.RangerService;
-import org.apache.ranger.plugin.model.RangerServiceDef;
-import org.apache.ranger.plugin.store.ServiceStore;
-
-import com.google.common.collect.Sets;
-
-public class RangerServiceValidator extends RangerValidator {
-
-	private static final Log LOG = LogFactory.getLog(RangerServiceValidator.class);
-
-	public RangerServiceValidator(ServiceStore store) {
-		super(store);
-	}
-
-	public void validate(RangerService service, Action action) throws Exception {
-		if(LOG.isDebugEnabled()) {
-			LOG.debug(String.format("==> RangerServiceValidator.validate(%s, %s)", service, action));
-		}
-
-		List<ValidationFailureDetails> failures = new ArrayList<ValidationFailureDetails>();
-		boolean valid = isValid(service, action, failures);
-		String message = "";
-		try {
-			if (!valid) {
-				message = serializeFailures(failures);
-				throw new Exception(message);
-			}
-		} finally {
-			if(LOG.isDebugEnabled()) {
-				LOG.debug(String.format("<== RangerServiceValidator.validate(%s, %s): %s, reason[%s]", service, action, valid, message));
-			}
-		}
-	}
-	
-	boolean isValid(Long id, Action action, List<ValidationFailureDetails> failures) {
-		if(LOG.isDebugEnabled()) {
-			LOG.debug("==> RangerServiceValidator.isValid(" + id + ")");
-		}
-
-		boolean valid = true;
-		if (action != Action.DELETE) {
-			failures.add(new ValidationFailureDetailsBuilder()
-				.isAnInternalError()
-				.becauseOf("unsupported action[" + action + "]; isValid(Long) is only supported for DELETE")
-				.build());
-			valid = false;
-		} else if (id == null) {
-			failures.add(new ValidationFailureDetailsBuilder()
-				.field("id")
-				.isMissing()
-				.build());
-			valid = false;
-		} else if (getService(id) == null) {
-			failures.add(new ValidationFailureDetailsBuilder()
-				.field("id")
-				.isSemanticallyIncorrect()
-				.becauseOf("no service found for id[" + id + "]")
-				.build());
-			valid = false;
-		}
-
-		if(LOG.isDebugEnabled()) {
-			LOG.debug("<== RangerServiceValidator.isValid(" + id + "): " + valid);
-		}
-		return valid;
-	}
-	
-	boolean isValid(RangerService service, Action action, List<ValidationFailureDetails> failures) {
-		if(LOG.isDebugEnabled()) {
-			LOG.debug("==> RangerServiceValidator.isValid(" + service + ")");
-		}
-		if (!(action == Action.CREATE || action == Action.UPDATE)) {
-			throw new IllegalArgumentException("isValid(RangerService, ...) is only supported for CREATE/UPDATE");
-		}
-		
-		boolean valid = true;
-		if (service == null) {
-			String message = "service object passed in was null";
-			LOG.debug(message);
-			failures.add(new ValidationFailureDetailsBuilder()
-				.field("service")
-				.isMissing()
-				.becauseOf(message)
-				.build());
-			valid = false;
-		} else {
-			Long id = service.getId();
-			if (action == Action.UPDATE) { // id is ignored for CREATE
-				if (id == null) {
-					String message = "service id was null/empty/blank"; 
-					LOG.debug(message);
-					failures.add(new ValidationFailureDetailsBuilder()
-						.field("id")
-						.isMissing()
-						.becauseOf(message)
-						.build());
-					valid = false;
-				} else if (getService(id) == null) {
-					failures.add(new ValidationFailureDetailsBuilder()
-						.field("id")
-						.isSemanticallyIncorrect()
-						.becauseOf("no service exists with id[" + id +"]")
-						.build());
-					valid = false;
-				}
-			}
-			String name = service.getName();
-			boolean nameSpecified = StringUtils.isNotBlank(name);
-			RangerServiceDef serviceDef = null;
-			if (!nameSpecified) {
-				String message = "service name[" + name + "] was null/empty/blank"; 
-				LOG.debug(message);
-				failures.add(new ValidationFailureDetailsBuilder()
-					.field("name")
-					.isMissing()
-					.becauseOf(message)
-					.build());
-				valid = false;
-			} else {
-				RangerService otherService = getService(name);
-				if (otherService != null && action == Action.CREATE) {
-					failures.add(new ValidationFailureDetailsBuilder()
-						.field("name")
-						.isSemanticallyIncorrect()
-						.becauseOf("service with the name[" + name + "] already exists")
-						.build());
-					valid = false;
-				} else if (otherService != null && otherService.getId() !=null && otherService.getId() != id) {
-					failures.add(new ValidationFailureDetailsBuilder()
-						.field("id/name")
-						.isSemanticallyIncorrect()
-						.becauseOf("id/name conflict: another service already exists with name[" + name + "], its id is [" + otherService.getId() + "]")
-						.build());
-					valid = false;
-				}
-			}
-			String type = service.getType();
-			boolean typeSpecified = StringUtils.isNotBlank(type);
-			if (!typeSpecified) {
-				failures.add(new ValidationFailureDetailsBuilder()
-					.field("type")
-					.isMissing()
-					.becauseOf("service def [" + type + "] was null/empty/blank")
-					.build());
-				valid = false;
-			} else {
-				serviceDef = getServiceDef(type);
-				if (serviceDef == null) {
-					failures.add(new ValidationFailureDetailsBuilder()
-						.field("type")
-						.isSemanticallyIncorrect()
-						.becauseOf("service def named[" + type + "] not found")
-						.build());
-					valid = false;
-				}
-			}
-			if (nameSpecified && serviceDef != null) {
-				// check if required parameters were specified
-				Set<String> reqiredParameters = getRequiredParameters(serviceDef);
-				Set<String> inputParameters = getServiceConfigParameters(service);
-				Set<String> missingParameters = Sets.difference(reqiredParameters, inputParameters);
-				if (!missingParameters.isEmpty()) {
-					failures.add(new ValidationFailureDetailsBuilder()
-						.field("configuration")
-						.subField(missingParameters.iterator().next()) // we return any one parameter!
-						.isMissing()
-						.becauseOf("required configuration parameter is missing; missing parameters: " + missingParameters)
-						.build());
-					valid = false;
-				}
-			}
-		}
-		
-		if(LOG.isDebugEnabled()) {
-			LOG.debug("<== RangerServiceValidator.isValid(" + service + "): " + valid);
-		}
-		return valid;
-	}
-}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/security-admin/src/main/java/org/apache/ranger/rest/RangerValidator.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/rest/RangerValidator.java b/security-admin/src/main/java/org/apache/ranger/rest/RangerValidator.java
deleted file mode 100644
index dc8ea65..0000000
--- a/security-admin/src/main/java/org/apache/ranger/rest/RangerValidator.java
+++ /dev/null
@@ -1,480 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF 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.apache.ranger.rest;
-
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.commons.collections.CollectionUtils;
-import org.apache.commons.lang.StringUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.ranger.plugin.model.RangerPolicy;
-import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
-import org.apache.ranger.plugin.model.RangerService;
-import org.apache.ranger.plugin.model.RangerServiceDef;
-import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef;
-import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumDef;
-import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
-import org.apache.ranger.plugin.model.RangerServiceDef.RangerServiceConfigDef;
-import org.apache.ranger.plugin.store.ServiceStore;
-import org.apache.ranger.plugin.util.SearchFilter;
-
-public abstract class RangerValidator {
-	
-	private static final Log LOG = LogFactory.getLog(RangerValidator.class);
-
-	ServiceStore _store;
-
-	public enum Action {
-		CREATE, UPDATE, DELETE;
-	};
-	
-	protected RangerValidator(ServiceStore store) {
-		if (store == null) {
-			throw new IllegalArgumentException("ServiceValidator(): store is null!");
-		}
-		_store = store;
-	}
-
-	public void validate(Long id, Action action) throws Exception {
-		if(LOG.isDebugEnabled()) {
-			LOG.debug("==> RangerValidator.validate(" + id + ")");
-		}
-
-		List<ValidationFailureDetails> failures = new ArrayList<ValidationFailureDetails>();
-		if (isValid(id, action, failures)) {
-			if(LOG.isDebugEnabled()) {
-				LOG.debug("<== RangerValidator.validate(" + id + "): valid");
-			}
-		} else {
-			String message = serializeFailures(failures);
-			LOG.debug("<== RangerValidator.validate(" + id + "): invalid, reason[" + message + "]");
-			throw new Exception(message);
-		}
-	}
-	
-	/**
-	 * This method is expected to be overridden by sub-classes.  Default implementation provided to not burden implementers from having to implement methods that they know would never be called. 
-	 * @param id
-	 * @param action
-	 * @param failures
-	 * @return
-	 */
-	boolean isValid(Long id, Action action, List<ValidationFailureDetails> failures) {
-		failures.add(new ValidationFailureDetailsBuilder()
-				.isAnInternalError()
-				.becauseOf("unimplemented method called")
-				.build());
-		return false;
-	}
-
-	String serializeFailures(List<ValidationFailureDetails> failures) {
-		if(LOG.isDebugEnabled()) {
-			LOG.debug("==> RangerValidator.getFailureMessage()");
-		}
-
-		String message = null;
-		if (CollectionUtils.isEmpty(failures)) {
-			LOG.warn("serializeFailures: called while list of failures is null/empty!");
-		} else {
-			StringBuilder builder = new StringBuilder();
-			for (ValidationFailureDetails aFailure : failures) {
-				builder.append(aFailure.toString());
-				builder.append(";");
-			}
-			message = builder.toString();
-		}
-
-		if(LOG.isDebugEnabled()) {
-			LOG.debug("<== RangerValidator.serializeFailures(): " + message);
-		}
-		return message;
-	}
-
-	Set<String> getServiceConfigParameters(RangerService service) {
-		if (service == null || service.getConfigs() == null) {
-			return new HashSet<String>();
-		} else {
-			return service.getConfigs().keySet();
-		}
-	}
-
-	Set<String> getRequiredParameters(RangerServiceDef serviceDef) {
-		if(LOG.isDebugEnabled()) {
-			LOG.debug("==> RangerValidator.getRequiredParameters(" + serviceDef + ")");
-		}
-
-		Set<String> result;
-		if (serviceDef == null) {
-			result = Collections.emptySet();
-		} else {
-			List<RangerServiceConfigDef> configs = serviceDef.getConfigs();
-			if (CollectionUtils.isEmpty(configs)) {
-				result = Collections.emptySet();
-			} else {
-				result = new HashSet<String>(configs.size()); // at worse all of the config items are required!
-				for (RangerServiceConfigDef configDef : configs) {
-					if (configDef.getMandatory()) {
-						result.add(configDef.getName());
-					}
-				}
-			}
-		}
-
-		if(LOG.isDebugEnabled()) {
-			LOG.debug("<== RangerValidator.getRequiredParameters(" + serviceDef + "): " + result);
-		}
-		return result;
-	}
-
-	RangerServiceDef getServiceDef(Long id) {
-
-		if(LOG.isDebugEnabled()) {
-			LOG.debug("==> RangerValidator.getServiceDef(" + id + ")");
-		}
-		RangerServiceDef result = null;
-		try {
-			result = _store.getServiceDef(id);
-		} catch (Exception e) {
-			LOG.debug("Encountred exception while retrieving service def from service store!", e);
-		}
-		
-		if(LOG.isDebugEnabled()) {
-			LOG.debug("<== RangerValidator.getServiceDef(" + id + "): " + result);
-		}
-		return result;
-	}
-
-	RangerServiceDef getServiceDef(String type) {
-		
-		if(LOG.isDebugEnabled()) {
-			LOG.debug("==> RangerValidator.getServiceDef(" + type + ")");
-		}
-		RangerServiceDef result = null;
-		try {
-			result = _store.getServiceDefByName(type);
-		} catch (Exception e) {
-			LOG.debug("Encountred exception while retrieving service definition from service store!", e);
-		}
-		
-		if(LOG.isDebugEnabled()) {
-			LOG.debug("<== RangerValidator.getServiceDef(" + type + "): " + result);
-		}
-		return result;
-	}
-
-	RangerService getService(Long id) {
-		
-		if(LOG.isDebugEnabled()) {
-			LOG.debug("==> RangerValidator.getService(" + id + ")");
-		}
-		RangerService result = null;
-		try {
-			result = _store.getService(id);
-		} catch (Exception e) {
-			LOG.debug("Encountred exception while retrieving service from service store!", e);
-		}
-		
-		if(LOG.isDebugEnabled()) {
-			LOG.debug("<== RangerValidator.getService(" + id + "): " + result);
-		}
-		return result;
-	}
-
-	RangerService getService(String name) {
-		
-		if(LOG.isDebugEnabled()) {
-			LOG.debug("==> RangerValidator.getService(" + name + ")");
-		}
-		RangerService result = null;
-		try {
-			result = _store.getServiceByName(name);
-		} catch (Exception e) {
-			LOG.debug("Encountred exception while retrieving service from service store!", e);
-		}
-		
-		if(LOG.isDebugEnabled()) {
-			LOG.debug("<== RangerValidator.getService(" + name + "): " + result);
-		}
-		return result;
-	}
-
-	RangerPolicy getPolicy(Long id) {
-		
-		if(LOG.isDebugEnabled()) {
-			LOG.debug("==> RangerValidator.getPolicy(" + id + ")");
-		}
-		RangerPolicy result = null;
-		try {
-			result = _store.getPolicy(id);
-		} catch (Exception e) {
-			LOG.debug("Encountred exception while retrieving policy from service store!", e);
-		}
-		
-		if(LOG.isDebugEnabled()) {
-			LOG.debug("<== RangerValidator.getPolicy(" + id + "): " + result);
-		}
-		return result;
-	}
-
-	List<RangerPolicy> getPolicies(final String policyName, final String serviceName) {
-		if(LOG.isDebugEnabled()) {
-			LOG.debug("==> RangerValidator.getPolicies(" + policyName + ", " + serviceName + ")");
-		}
-
-		List<RangerPolicy> policies = null;
-		try {
-			SearchFilter filter = new SearchFilter();
-			filter.setParam(SearchFilter.POLICY_NAME, policyName);
-			filter.setParam(SearchFilter.SERVICE_NAME, serviceName);
-			
-			policies = _store.getPolicies(filter);
-		} catch (Exception e) {
-			LOG.debug("Encountred exception while retrieving service from service store!", e);
-		}
-		
-		if(LOG.isDebugEnabled()) {
-			LOG.debug("<== RangerValidator.getPolicies(" + policyName + ", " + serviceName + "): " + policies);
-		}
-		return policies;
-	}
-
-	Set<String> getAccessTypes(RangerServiceDef serviceDef) {
-		if(LOG.isDebugEnabled()) {
-			LOG.debug("==> RangerValidator.getAccessTypes(" + serviceDef + ")");
-		}
-
-		Set<String> accessTypes = new HashSet<String>();
-		if (serviceDef == null) {
-			LOG.warn("serviceDef passed in was null!");
-		} else if (CollectionUtils.isEmpty(serviceDef.getAccessTypes())) {
-			LOG.warn("AccessTypeDef collection on serviceDef was null!");
-		} else {
-			for (RangerAccessTypeDef accessTypeDef : serviceDef.getAccessTypes()) {
-				if (accessTypeDef == null) {
-					LOG.warn("Access type def was null!");
-				} else {
-					String accessType = accessTypeDef.getName();
-					if (StringUtils.isBlank(accessType)) {
-						LOG.warn("Access type def name was null/empty/blank!");
-					} else {
-						accessTypes.add(accessType.toLowerCase());
-					}
-				}
-			}
-		}
-
-		if(LOG.isDebugEnabled()) {
-			LOG.debug("<== RangerValidator.getAccessTypes(" + serviceDef + "): " + accessTypes);
-		}
-		return accessTypes;
-	}
-	
-	/**
-	 * This function exists to encapsulates the current behavior of code which treats and unspecified audit preference to mean audit is enabled.
-	 * @param policy
-	 * @return
-	 */
-	boolean getIsAuditEnabled(RangerPolicy policy) {
-		if(LOG.isDebugEnabled()) {
-			LOG.debug("<== RangerValidator.getIsAuditEnabled(" + policy + ")");
-		}
-
-		boolean isEnabled = false;
-		if (policy == null) {
-			LOG.warn("policy was null!");
-		} else if (policy.getIsAuditEnabled() == null) {
-			isEnabled = true;
-		} else {
-			isEnabled = policy.getIsAuditEnabled();
-		}
-
-		if(LOG.isDebugEnabled()) {
-			LOG.debug("<== RangerValidator.getIsAuditEnabled(" + policy + "): " + isEnabled);
-		}
-		return isEnabled;
-	}
-	
-	/**
-	 * Returns names of resource types set to lower-case to allow for case-insensitive comparison. 
-	 * @param serviceDef
-	 * @return
-	 */
-	Set<String> getMandatoryResourceNames(RangerServiceDef serviceDef) {
-		if(LOG.isDebugEnabled()) {
-			LOG.debug("==> RangerValidator.getMandatoryResourceNames(" + serviceDef + ")");
-		}
-
-		Set<String> resourceNames = new HashSet<String>();
-		if (serviceDef == null) {
-			LOG.warn("serviceDef passed in was null!");
-		} else if (CollectionUtils.isEmpty(serviceDef.getResources())) {
-			LOG.warn("ResourceDef collection on serviceDef was null!");
-		} else {
-			for (RangerResourceDef resourceTypeDef : serviceDef.getResources()) {
-				if (resourceTypeDef == null) {
-					LOG.warn("resource type def was null!");
-				} else {
-					Boolean mandatory = resourceTypeDef.getMandatory();
-					if (mandatory != null && mandatory == true) {
-						String resourceName = resourceTypeDef.getName();
-						if (StringUtils.isBlank(resourceName)) {
-							LOG.warn("Resource def name was null/empty/blank!");
-						} else {
-							resourceNames.add(resourceName.toLowerCase());
-						}
-					}
-				}
-			}
-		}
-
-		if(LOG.isDebugEnabled()) {
-			LOG.debug("<== RangerValidator.getMandatoryResourceNames(" + serviceDef + "): " + resourceNames);
-		}
-		return resourceNames;
-	}
-
-	Set<String> getAllResourceNames(RangerServiceDef serviceDef) {
-		if(LOG.isDebugEnabled()) {
-			LOG.debug("==> RangerValidator.getAllResourceNames(" + serviceDef + ")");
-		}
-
-		Set<String> resourceNames = new HashSet<String>();
-		if (serviceDef == null) {
-			LOG.warn("serviceDef passed in was null!");
-		} else if (CollectionUtils.isEmpty(serviceDef.getResources())) {
-			LOG.warn("ResourceDef collection on serviceDef was null!");
-		} else {
-			for (RangerResourceDef resourceTypeDef : serviceDef.getResources()) {
-				if (resourceTypeDef == null) {
-					LOG.warn("resource type def was null!");
-				} else {
-					String resourceName = resourceTypeDef.getName();
-					if (StringUtils.isBlank(resourceName)) {
-						LOG.warn("Resource def name was null/empty/blank!");
-					} else {
-						resourceNames.add(resourceName.toLowerCase());
-					}
-				}
-			}
-		}
-
-		if(LOG.isDebugEnabled()) {
-			LOG.debug("<== RangerValidator.getAllResourceNames(" + serviceDef + "): " + resourceNames);
-		}
-		return resourceNames;
-	}
-	
-	/**
-	 * Returns the resource-types defined on the policy converted to lowe-case
-	 * @param policy
-	 * @return
-	 */
-	Set<String> getPolicyResources(RangerPolicy policy) {
-		if (policy == null || policy.getResources() == null || policy.getResources().isEmpty()) {
-			return new HashSet<String>();
-		} else {
-			Set<String> result = new HashSet<String>();
-			for (String name : policy.getResources().keySet()) {
-				result.add(name.toLowerCase());
-			}
-			return result;
-		}
-	}
-
-	Map<String, String> getValidationRegExes(RangerServiceDef serviceDef) {
-		if (serviceDef == null || CollectionUtils.isEmpty(serviceDef.getResources())) {
-			return new HashMap<String, String>();
-		} else {
-			Map<String, String> result = new HashMap<String, String>();
-			for (RangerResourceDef resourceDef : serviceDef.getResources()) {
-				if (resourceDef == null) {
-					LOG.warn("A resource def in resource def collection is null");
-				} else {
-					String name = resourceDef.getName();
-					String regEx = resourceDef.getValidationRegEx();
-					if (StringUtils.isBlank(name)) {
-						LOG.warn("resource name is null/empty/blank");
-					} else if (StringUtils.isBlank(regEx)) {
-						LOG.debug("validation regex is null/empty/blank");
-					} else {
-						result.put(name, regEx);
-					}
-				}
-			}
-			return result;
-		}
-	}
-	
-	int getEnumDefaultIndex(RangerEnumDef enumDef) {
-		int index;
-		if (enumDef == null) {
-			index = -1;
-		} else if (enumDef.getDefaultIndex() == null) {
-			index = 0;
-		} else {
-			index = enumDef.getDefaultIndex();
-		}
-		return index;
-	}
-
-	Collection<String> getImpliedGrants(RangerAccessTypeDef def) {
-		if (def == null) {
-			return null;
-		} else if (CollectionUtils.isEmpty(def.getImpliedGrants())) {
-			return new ArrayList<String>();
-		} else {
-			List<String> result = new ArrayList<String>(def.getImpliedGrants().size());
-			for (String name : def.getImpliedGrants()) {
-				if (StringUtils.isBlank(name)) {
-					result.add(name); // could be null!
-				} else {
-					result.add(name.toLowerCase());
-				}
-			}
-			return result;
-		}
-	}
-
-	/**
-	 * Returns a copy of the policy resource map where all keys (resource-names) are lowercase
-	 * @param input
-	 * @return
-	 */
-	Map<String, RangerPolicyResource> getPolicyResourceWithLowerCaseKeys(Map<String, RangerPolicyResource> input) {
-		if (input == null) {
-			return null;
-		}
-		Map<String, RangerPolicyResource> output = new HashMap<String, RangerPolicyResource>(input.size());
-		for (Map.Entry<String, RangerPolicyResource> entry : input.entrySet()) {
-			output.put(entry.getKey().toLowerCase(), entry.getValue());
-		}
-		return output;
-	}
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/security-admin/src/main/java/org/apache/ranger/rest/RangerValidatorFactory.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/rest/RangerValidatorFactory.java b/security-admin/src/main/java/org/apache/ranger/rest/RangerValidatorFactory.java
deleted file mode 100644
index 9ca52f3..0000000
--- a/security-admin/src/main/java/org/apache/ranger/rest/RangerValidatorFactory.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF 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.apache.ranger.rest;
-
-import org.apache.ranger.plugin.store.ServiceStore;
-
-public class RangerValidatorFactory {
-	public RangerServiceValidator getServiceValidator(ServiceStore store) {
-		return new RangerServiceValidator(store);
-	}
-
-	public RangerPolicyValidator getPolicyValidator(ServiceStore store) {
-		return new RangerPolicyValidator(store);
-	}
-
-	public RangerServiceDefValidator getServiceDefValidator(ServiceStore store) {
-		return new RangerServiceDefValidator(store);
-	}
-}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/security-admin/src/main/java/org/apache/ranger/rest/ServiceREST.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/rest/ServiceREST.java b/security-admin/src/main/java/org/apache/ranger/rest/ServiceREST.java
index 85c75f3..470ca50 100644
--- a/security-admin/src/main/java/org/apache/ranger/rest/ServiceREST.java
+++ b/security-admin/src/main/java/org/apache/ranger/rest/ServiceREST.java
@@ -56,6 +56,11 @@ import org.apache.ranger.plugin.model.RangerPolicy;
 import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItem;
 import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemAccess;
 import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
+import org.apache.ranger.plugin.model.validation.RangerPolicyValidator;
+import org.apache.ranger.plugin.model.validation.RangerServiceDefValidator;
+import org.apache.ranger.plugin.model.validation.RangerServiceValidator;
+import org.apache.ranger.plugin.model.validation.RangerValidatorFactory;
+import org.apache.ranger.plugin.model.validation.RangerValidator.Action;
 import org.apache.ranger.plugin.model.RangerService;
 import org.apache.ranger.plugin.model.RangerServiceDef;
 import org.apache.ranger.plugin.policyengine.RangerPolicyEngine;
@@ -67,7 +72,6 @@ import org.apache.ranger.plugin.service.ResourceLookupContext;
 import org.apache.ranger.plugin.util.GrantRevokeRequest;
 import org.apache.ranger.plugin.util.SearchFilter;
 import org.apache.ranger.plugin.util.ServicePolicies;
-import org.apache.ranger.rest.RangerValidator.Action;
 import org.apache.ranger.view.VXResponse;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Scope;

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/security-admin/src/main/java/org/apache/ranger/rest/ValidationFailureDetails.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/rest/ValidationFailureDetails.java b/security-admin/src/main/java/org/apache/ranger/rest/ValidationFailureDetails.java
deleted file mode 100644
index 8ceeba1..0000000
--- a/security-admin/src/main/java/org/apache/ranger/rest/ValidationFailureDetails.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF 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.apache.ranger.rest;
-
-import java.util.Objects;
-
-public class ValidationFailureDetails {
-
-	final String _fieldName;
-	final String _subFieldName;
-	final boolean _missing;
-	final boolean _semanticError;
-	final boolean _internalError;
-	final String _reason;
-	
-	public ValidationFailureDetails(String fieldName, String subFieldName, boolean missing, boolean semanticError, boolean internalError, String reason) {
-		_missing = missing;
-		_semanticError = semanticError;
-		_internalError = internalError;
-		_fieldName = fieldName;
-		_subFieldName = subFieldName;
-		_reason = reason;
-	}
-
-	public String getFieldName() {
-		return _fieldName;
-	}
-
-	public boolean isMissingRequiredValue() {
-		return _missing;
-	}
-
-	public boolean isSemanticallyIncorrect() {
-		return _semanticError;
-	}
-	
-	String getType() {
-		if (_missing) return "missing";
-		if (_semanticError) return "semantically incorrect";
-		if (_internalError) return "internal error";
-		return "";
-	}
-
-	public String getSubFieldName() {
-		return _subFieldName;
-	}
-	
-	@Override
-	public String toString() {
-		return String.format("Field[%s]%s is %s: reason[%s]", 
-				_fieldName, 
-				_subFieldName == null ? "" : ", subField[" + _subFieldName + "]",
-				getType(), _reason);
-	}
-	
-	@Override
-	public int hashCode() {
-		return Objects.hash(_fieldName, _subFieldName, _missing, _semanticError, _internalError, _reason);
-	}
-	
-	@Override
-	public boolean equals(Object obj) {
-		if (obj == null || !(obj instanceof ValidationFailureDetails)) {
-			return false;
-		}
-		ValidationFailureDetails that = (ValidationFailureDetails)obj;
-		return Objects.equals(_fieldName, that._fieldName) && 
-				Objects.equals(_subFieldName, that._subFieldName) && 
-				Objects.equals(_reason, that._reason) && 
-				_internalError == that._internalError &&
-				_missing == that._missing &&
-				_semanticError == that._semanticError;
-	}
-}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/security-admin/src/main/java/org/apache/ranger/rest/ValidationFailureDetailsBuilder.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/rest/ValidationFailureDetailsBuilder.java b/security-admin/src/main/java/org/apache/ranger/rest/ValidationFailureDetailsBuilder.java
deleted file mode 100644
index b85215d..0000000
--- a/security-admin/src/main/java/org/apache/ranger/rest/ValidationFailureDetailsBuilder.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF 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.apache.ranger.rest;
-
-public class ValidationFailureDetailsBuilder {
-	private String _fieldName;
-	private boolean _missing;
-	private boolean _semanticError;
-	private String _reason;
-	private String _subFieldName;
-	private boolean _internalError;
-	
-	ValidationFailureDetailsBuilder becauseOf(String aReason) {
-		_reason = aReason;
-		return this;
-	}
-	
-	ValidationFailureDetailsBuilder isMissing() {
-		_missing = true;
-		return this;
-	}
-	
-	ValidationFailureDetailsBuilder isSemanticallyIncorrect() {
-		_semanticError = true;
-		return this;
-	}
-	
-	ValidationFailureDetailsBuilder field(String fieldName) {
-		_fieldName = fieldName;
-		return this;
-	}
-	
-	ValidationFailureDetails build() {
-		return new ValidationFailureDetails(_fieldName, _subFieldName, _missing, _semanticError, _internalError, _reason);
-	}
-
-	ValidationFailureDetailsBuilder subField(String missingParameter) {
-		_subFieldName = missingParameter;
-		return this;
-	}
-
-	ValidationFailureDetailsBuilder isAnInternalError() {
-		_internalError = true;
-		return this;
-	}
-
-}


[3/4] incubator-ranger git commit: RANGER-278 move validation classes under org.apache.ranger.plugin.model.validation

Posted by ma...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerPolicyValidator.java
----------------------------------------------------------------------
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerPolicyValidator.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerPolicyValidator.java
new file mode 100644
index 0000000..e0f68ad
--- /dev/null
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerPolicyValidator.java
@@ -0,0 +1,524 @@
+package org.apache.ranger.plugin.model.validation;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.ranger.plugin.model.RangerPolicy;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItem;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemAccess;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
+import org.apache.ranger.plugin.model.RangerService;
+import org.apache.ranger.plugin.model.RangerServiceDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
+import org.apache.ranger.plugin.model.validation.RangerPolicyValidator;
+import org.apache.ranger.plugin.model.validation.ValidationFailureDetails;
+import org.apache.ranger.plugin.model.validation.RangerValidator.Action;
+import org.apache.ranger.plugin.store.ServiceStore;
+import org.apache.ranger.plugin.util.SearchFilter;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Sets;
+
+public class TestRangerPolicyValidator {
+
+	@Before
+	public void setUp() throws Exception {
+		_store = mock(ServiceStore.class);
+		_policy = mock(RangerPolicy.class);
+		_validator = new RangerPolicyValidator(_store);
+		_serviceDef = mock(RangerServiceDef.class);
+	}
+	
+	final Action[] cu = new Action[] { Action.CREATE, Action.UPDATE };
+	final Object[] policyItemsData = new Object[] {
+			ImmutableMap.of(  // all good
+				"users", new String[] {"user1" ," user2"},
+				"groups", new String[] {"group1", "group2"},
+				"accesses", new String[] { "r", "w" },
+				"isAllowed", new Boolean[] { true, true }),
+			ImmutableMap.of(   // no users, access type different case
+				"groups", new String[] {"group3", "group4"},
+				"accesses", new String[]{"W", "x"}, 
+				"isAllowed", new Boolean[] { true, true }),
+			ImmutableMap.of(   // no groups
+				"users", new String[] {"user3" ," user4"}, 
+				"accesses", new String[] { "r", "x" },
+				"isAllowed", new Boolean[] { true, true }),
+			ImmutableMap.of( // isallowed on access types is null, case is different from that in definition
+				"users", new String[] {"user7" ," user6"},
+				"accesses", new String[] { "a" },
+				"isAllowed", new Boolean[] { null, null })
+	};
+	String[] accessTypes = new String[] { "r", "w", "x", "A" };  // mix of lower and upper case
+	String[] accessTypes_bad = new String[] { "r", "w", "xx", }; // two missing (x, a), one new that isn't on bad (xx)
+	
+	private final Object[][] resourceDefData = new Object[][] {
+			// { name, mandatory, reg-exp, excludesSupported, recursiveSupported }
+			{ "db", true, "db\\d+", null, null }, // valid values: db1, db22, db983, etc.; invalid: db, db12x, ttx11, etc.; null => false for excludes and recursive
+			{ "tbl", true, null, true, true }, // regex == null => anything goes; excludes == true, recursive == true
+			{ "col", false, "col\\d{1,2}", false, true }  // valid: col1, col47, etc.; invalid: col, col238, col1, etc., excludes == false, recursive == true 
+	};
+	
+	private final Object[][] policyResourceMap_good = new Object[][] {
+			// resource-name, values, excludes, recursive
+			{ "db", new String[] { "db1", "db2" }, null, null },
+			{ "TBL", new String[] { "tbl1", "tbl2" }, true, false } // case should not matter
+	};
+	
+	private final Object[][] policyResourceMap_bad = new Object[][] {
+			// resource-name, values, excludes, recursive
+			{ "db", new String[] { "db1", "db2" }, null, true },        // mandatory "tbl" missing; recursive==true specified when resource-def does not support it (null) 
+			{"col", new String[] { "col12", "col 1" }, true, true },    // wrong format of value for "col"; excludes==true specified when resource-def does not allow it (false)
+			{"extra", new String[] { "extra1", "extra2" }, null, null } // spurious "extra" specified
+	};
+
+	@Test
+	public final void testIsValid_long() throws Exception {
+		// this validation should be removed if we start supporting other than delete action
+		assertFalse(_validator.isValid(3L, Action.CREATE, _failures));
+		_utils.checkFailureForInternalError(_failures);
+		
+		// should fail with appropriate error message if id is null
+		_failures.clear(); _failures.clear(); assertFalse(_validator.isValid((Long)null, Action.DELETE, _failures));
+		_utils.checkFailureForMissingValue(_failures, "id");
+		
+		// should fail with appropriate error message if policy can't be found for the specified id
+		when(_store.getPolicy(1L)).thenReturn(null);
+		when(_store.getPolicy(2L)).thenThrow(new Exception());
+		RangerPolicy existingPolicy = mock(RangerPolicy.class);
+		when(_store.getPolicy(3L)).thenReturn(existingPolicy);
+		_failures.clear(); assertFalse(_validator.isValid(1L, Action.DELETE, _failures));
+		_utils.checkFailureForSemanticError(_failures, "id");
+		_failures.clear(); assertFalse(_validator.isValid(2L, Action.DELETE, _failures));
+		_utils.checkFailureForSemanticError(_failures, "id");
+
+		// if policy exists then delete validation should pass 
+		assertTrue(_validator.isValid(3L, Action.DELETE, _failures));
+	}
+	
+	@Test
+	public final void testIsValid_happyPath() throws Exception {
+		// valid policy has valid non-empty name and service name 
+		when(_policy.getService()).thenReturn("service-name");
+		// service name exists
+		RangerService service = mock(RangerService.class);
+		when(service.getType()).thenReturn("service-type");
+		when(_store.getServiceByName("service-name")).thenReturn(service);
+		// service points to a valid service-def
+		_serviceDef = _utils.createServiceDefWithAccessTypes(accessTypes);
+		when(_store.getServiceDefByName("service-type")).thenReturn(_serviceDef);
+		// a matching policy should exist for create when checked by id and not exist when checked by name.
+		when(_store.getPolicy(7L)).thenReturn(null);
+		RangerPolicy existingPolicy = mock(RangerPolicy.class);
+		when(existingPolicy.getId()).thenReturn(8L);
+		when(_store.getPolicy(8L)).thenReturn(existingPolicy);
+		SearchFilter createFilter = new SearchFilter();
+		createFilter.setParam(SearchFilter.POLICY_NAME, "service-type");
+		createFilter.setParam(SearchFilter.POLICY_NAME, "policy-name-1"); // this name would be used for create
+		when(_store.getPolicies(createFilter)).thenReturn(new ArrayList<RangerPolicy>());
+		// a matching policy should not exist for update.
+		SearchFilter updateFilter = new SearchFilter();
+		updateFilter.setParam(SearchFilter.POLICY_NAME, "service-type");
+		updateFilter.setParam(SearchFilter.POLICY_NAME, "policy-name-2"); // this name would be used for update
+		List<RangerPolicy> existingPolicies = new ArrayList<RangerPolicy>();
+		existingPolicies.add(existingPolicy);
+		when(_store.getPolicies(updateFilter)).thenReturn(existingPolicies);
+		// valid policy can have empty set of policy items if audit is turned on
+		// null value for audit is treated as audit on.
+		for (Action action : cu) {
+			for (Boolean auditEnabled : new Boolean[] { null, true } ) {
+				when(_policy.getIsAuditEnabled()).thenReturn(auditEnabled);
+				if (action == Action.CREATE) {
+					when(_policy.getId()).thenReturn(7L);
+					when(_policy.getName()).thenReturn("policy-name-1");
+					assertTrue("" + action + ", " + auditEnabled, _validator.isValid(_policy, action, _failures));
+					assertTrue(_failures.isEmpty());
+				} else {
+					// update should work both when by-name is found or not, since nothing found by-name means name is being updated.
+					when(_policy.getId()).thenReturn(8L);
+					when(_policy.getName()).thenReturn("policy-name-1");
+					assertTrue("" + action + ", " + auditEnabled, _validator.isValid(_policy, action, _failures));
+					assertTrue(_failures.isEmpty());
+
+					when(_policy.getName()).thenReturn("policy-name-2");
+					assertTrue("" + action + ", " + auditEnabled, _validator.isValid(_policy, action, _failures));
+					assertTrue(_failures.isEmpty());
+				}
+			}
+		}
+		// if audit is disabled then policy should have policy items and all of them should be valid
+		List<RangerPolicyItem> policyItems = _utils.createPolicyItems(policyItemsData);
+		when(_policy.getPolicyItems()).thenReturn(policyItems);
+		when(_policy.getIsAuditEnabled()).thenReturn(false);
+		for (Action action : cu) {
+			if (action == Action.CREATE) {
+				when(_policy.getId()).thenReturn(7L);
+				when(_policy.getName()).thenReturn("policy-name-1");
+			} else {
+				when(_policy.getId()).thenReturn(8L);
+				when(_policy.getName()).thenReturn("policy-name-2");
+			}
+			assertTrue("" + action , _validator.isValid(_policy, action, _failures));
+			assertTrue(_failures.isEmpty());
+		}
+		
+		// above succeeded as service def did not have any resources on it, mandatory or otherwise.
+		// policy should have all mandatory resources specified, and they should conform to the validation pattern in resource definition
+		List<RangerResourceDef> resourceDefs = _utils.createResourceDefs(resourceDefData);
+		when(_serviceDef.getResources()).thenReturn(resourceDefs);
+		Map<String, RangerPolicyResource> resourceMap = _utils.createPolicyResourceMap(policyResourceMap_good);
+		when(_policy.getResources()).thenReturn(resourceMap);
+
+		for (Action action : cu) {
+			if (action == Action.CREATE) {
+				when(_policy.getId()).thenReturn(7L);
+				when(_policy.getName()).thenReturn("policy-name-1");
+			} else {
+				when(_policy.getId()).thenReturn(8L);
+				when(_policy.getName()).thenReturn("policy-name-2");
+			}
+			assertTrue("" + action , _validator.isValid(_policy, action, _failures));
+			assertTrue(_failures.isEmpty());
+		}
+	}
+	
+	void checkFailure_isValid(Action action, String errorType, String field) {
+		checkFailure_isValid(action, errorType, field, null);
+	}
+	
+	void checkFailure_isValid(Action action, String errorType, String field, String subField) {
+		_failures.clear();
+		assertFalse(_validator.isValid(_policy, action, _failures));
+		switch (errorType) {
+		case "missing":
+			_utils.checkFailureForMissingValue(_failures, field, subField);
+			break;
+		case "semantic":
+			_utils.checkFailureForSemanticError(_failures, field, subField);
+			break;
+		case "internal error":
+			_utils.checkFailureForInternalError(_failures);
+			break;
+		default:
+			fail("Unsupported errorType[" + errorType + "]");
+			break;
+		}
+	}
+	
+	@Test
+	public final void testIsValid_failures() throws Exception {
+		for (Action action : cu) {
+			// passing in a null policy should fail with appropriate failure reason
+			_policy = null;
+			checkFailure_isValid(action, "missing", "policy");
+			
+			// policy must have a name on it
+			_policy = mock(RangerPolicy.class);
+			for (String name : new String[] { null, "  " }) {
+				when(_policy.getName()).thenReturn(name);
+				checkFailure_isValid(action, "missing", "name");
+			}
+			
+			// for update id is required!
+			if (action == Action.UPDATE) {
+				when(_policy.getId()).thenReturn(null);
+				checkFailure_isValid(action, "missing", "id");
+			}
+		}
+		/*
+		 * Id is ignored for Create but name should not belong to an existing policy.  For update, policy should exist for its id and should match its name.
+		 */
+		when(_policy.getName()).thenReturn("policy-name");
+		when(_policy.getService()).thenReturn("service-name");
+
+		RangerPolicy existingPolicy = mock(RangerPolicy.class);
+		when(existingPolicy.getId()).thenReturn(7L);
+		List<RangerPolicy> existingPolicies = new ArrayList<RangerPolicy>();
+		existingPolicies.add(existingPolicy);
+		SearchFilter filter = new SearchFilter();
+		filter.setParam(SearchFilter.SERVICE_NAME, "service-name");
+		filter.setParam(SearchFilter.POLICY_NAME, "policy-name");
+		when(_store.getPolicies(filter)).thenReturn(existingPolicies);
+		checkFailure_isValid(Action.CREATE, "semantic", "name");
+		
+		// update : does not exist for id
+		when(_policy.getId()).thenReturn(7L);
+		when(_store.getPolicy(7L)).thenReturn(null);
+		checkFailure_isValid(Action.UPDATE, "semantic", "id");
+
+		// Update: name should not point to an existing different policy, i.e. with a different id
+		when(_store.getPolicy(7L)).thenReturn(existingPolicy);
+		RangerPolicy anotherExistingPolicy = mock(RangerPolicy.class);
+		when(anotherExistingPolicy.getId()).thenReturn(8L);
+		existingPolicies.clear();
+		existingPolicies.add(anotherExistingPolicy);
+		when(_store.getPolicies(filter)).thenReturn(existingPolicies);
+		checkFailure_isValid(Action.UPDATE, "semantic", "id/name");
+
+		// more than one policies with same name is also an internal error
+		when(_policy.getName()).thenReturn("policy-name");
+		when(_store.getPolicies(filter)).thenReturn(existingPolicies);
+		existingPolicies.add(existingPolicy);
+		existingPolicy = mock(RangerPolicy.class);
+		existingPolicies.add(existingPolicy);
+		_failures.clear(); assertFalse(_validator.isValid(_policy, Action.UPDATE, _failures));
+		_utils.checkFailureForInternalError(_failures);
+		
+		// policy must have service name on it and it should be valid
+		when(_policy.getName()).thenReturn("policy-name");
+		when(_store.getServiceByName("service-name")).thenReturn(null);
+		when(_store.getServiceByName("another-service-name")).thenThrow(new Exception());
+
+		for (Action action : cu) {
+			when(_policy.getService()).thenReturn("service-name");
+			_failures.clear(); assertFalse(_validator.isValid(_policy, action, _failures));
+			_utils.checkFailureForMissingValue(_failures, "service");
+
+			when(_policy.getService()).thenReturn("another-service-name");
+			_failures.clear(); assertFalse(_validator.isValid(_policy, action, _failures));
+			_utils.checkFailureForMissingValue(_failures, "service");
+		}
+		
+		// policy must contain at least one policy item
+		List<RangerPolicyItem> policyItems = new ArrayList<RangerPolicy.RangerPolicyItem>();
+		when(_policy.getService()).thenReturn("service-name");
+		RangerService service = mock(RangerService.class);
+		when(_store.getServiceByName("service-name")).thenReturn(service);
+		for (Action action : cu) {
+			// when it is null
+			when(_policy.getPolicyItems()).thenReturn(null);
+			_failures.clear(); assertFalse(_validator.isValid(_policy, action, _failures));
+			_utils.checkFailureForMissingValue(_failures, "policy items");
+			// or when it is not null but empty.
+			when(_policy.getPolicyItems()).thenReturn(policyItems);
+			_failures.clear(); assertFalse(_validator.isValid(_policy, action, _failures));
+			_utils.checkFailureForMissingValue(_failures, "policy items");
+		}
+		
+		// these are known good policy items -- same as used above in happypath
+		policyItems = _utils.createPolicyItems(policyItemsData);
+		when(_policy.getPolicyItems()).thenReturn(policyItems);
+		// policy item check requires that service def should exist
+		when(service.getType()).thenReturn("service-type");
+		when(_store.getServiceDefByName("service-type")).thenReturn(null);
+		for (Action action : cu) {
+			_failures.clear(); assertFalse(_validator.isValid(_policy, action, _failures));
+			_utils.checkFailureForInternalError(_failures, "policy service def");
+		}
+		
+		// service-def should contain the right access types on it.
+		_serviceDef = _utils.createServiceDefWithAccessTypes(accessTypes_bad);
+		when(_store.getServiceDefByName("service-type")).thenReturn(_serviceDef);
+		for (Action action : cu) {
+			_failures.clear(); assertFalse(_validator.isValid(_policy, action, _failures));
+			_utils.checkFailureForSemanticError(_failures, "policy item access type");
+		}
+
+		// create the right service def with right resource defs - this is the same as in the happypath test above.
+		_serviceDef = _utils.createServiceDefWithAccessTypes(accessTypes);
+		when(_store.getPolicies(filter)).thenReturn(null);
+		List<RangerResourceDef> resourceDefs = _utils.createResourceDefs(resourceDefData);
+		when(_serviceDef.getResources()).thenReturn(resourceDefs);
+		when(_store.getServiceDefByName("service-type")).thenReturn(_serviceDef);
+		// one mandtory is missing (tbl) and one unknown resource is specified (extra), and values of option resource don't conform to validation pattern (col)
+		Map<String, RangerPolicyResource> policyResources = _utils.createPolicyResourceMap(policyResourceMap_bad);
+		when(_policy.getResources()).thenReturn(policyResources);
+		for (Action action : cu) {
+			_failures.clear(); assertFalse(_validator.isValid(_policy, action, _failures));
+			_utils.checkFailureForMissingValue(_failures, "resources", "tbl"); // for missing resource: tbl
+			_utils.checkFailureForSemanticError(_failures, "resources", "extra"); // for spurious resource: "extra"
+			_utils.checkFailureForSemanticError(_failures, "resource-values", "col"); // for spurious resource: "extra"
+			_utils.checkFailureForSemanticError(_failures, "isRecursive", "db"); // for specifying it as true when def did not allow it
+			_utils.checkFailureForSemanticError(_failures, "isExcludes", "col"); // for specifying it as true when def did not allow it
+		}
+	}
+	
+	@Test
+	public void test_isValidResourceValues() {
+		List<RangerResourceDef> resourceDefs = _utils.createResourceDefs(resourceDefData);
+		when(_serviceDef.getResources()).thenReturn(resourceDefs);
+		Map<String, RangerPolicyResource> policyResources = _utils.createPolicyResourceMap(policyResourceMap_bad);
+		assertFalse(_validator.isValidResourceValues(policyResources, _failures, _serviceDef));
+		_utils.checkFailureForSemanticError(_failures, "resource-values", "col");
+		
+		policyResources = _utils.createPolicyResourceMap(policyResourceMap_good);
+		assertTrue(_validator.isValidResourceValues(policyResources, _failures, _serviceDef));
+	}
+	
+	@Test
+	public void test_isValidPolicyItems_failures() {
+		// null/empty list is good because there is nothing
+		assertTrue(_validator.isValidPolicyItems(null, _failures, _serviceDef));
+		_failures.isEmpty();
+
+		List<RangerPolicyItem> policyItems = new ArrayList<RangerPolicy.RangerPolicyItem>();
+		assertTrue(_validator.isValidPolicyItems(policyItems, _failures, _serviceDef));
+		_failures.isEmpty();
+		
+		// null elements in the list are flagged
+		policyItems.add(null);
+		assertFalse(_validator.isValidPolicyItems(policyItems, _failures, _serviceDef));
+		_utils.checkFailureForMissingValue(_failures, "policy item");
+	}
+	
+	@Test
+	public void test_isValidPolicyItem_failures() {
+
+		// empty access collections are invalid
+		RangerPolicyItem policyItem = mock(RangerPolicyItem.class);
+		when(policyItem.getAccesses()).thenReturn(null);
+		_failures.clear(); assertFalse(_validator.isValidPolicyItem(policyItem, _failures, _serviceDef));
+		_utils.checkFailureForMissingValue(_failures, "policy item accesses");
+
+		List<RangerPolicyItemAccess> accesses = new ArrayList<RangerPolicy.RangerPolicyItemAccess>();
+		when(policyItem.getAccesses()).thenReturn(accesses);
+		_failures.clear(); assertFalse(_validator.isValidPolicyItem(policyItem, _failures, _serviceDef));
+		_utils.checkFailureForMissingValue(_failures, "policy item accesses");
+		
+		// both user and groups can't be null
+		RangerPolicyItemAccess access = mock(RangerPolicyItemAccess.class);
+		accesses.add(access);
+		when(policyItem.getUsers()).thenReturn(null);
+		when(policyItem.getGroups()).thenReturn(new ArrayList<String>());
+		_failures.clear(); assertFalse(_validator.isValidPolicyItem(policyItem, _failures, _serviceDef));
+		_utils.checkFailureForMissingValue(_failures, "policy item users/user-groups");
+	}
+	
+	@Test
+	public void test_isValidItemAccesses_happyPath() {
+		
+		// happy path
+		Object[][] data = new Object[][] {
+				{ "a", null }, // valid
+				{ "b", true }, // valid
+				{ "c", true }, // valid
+		};
+		List<RangerPolicyItemAccess> accesses = _utils.createItemAccess(data);
+		_serviceDef = _utils.createServiceDefWithAccessTypes(new String[] { "a", "b", "c", "d" });
+		assertTrue(_validator.isValidItemAccesses(accesses, _failures, _serviceDef));
+		assertTrue(_failures.isEmpty());
+	}
+	
+	@Test
+	public void test_isValidItemAccesses_failure() {
+
+		// null policy item access values are an error
+		List<RangerPolicyItemAccess> accesses = new ArrayList<RangerPolicyItemAccess>();
+		accesses.add(null);
+		_failures.clear(); assertFalse(_validator.isValidItemAccesses(accesses, _failures, _serviceDef));
+		_utils.checkFailureForMissingValue(_failures, "policy item access");
+
+		// all items must be valid for this call to be valid
+		Object[][] data = new Object[][] {
+				{ "a", null }, // valid
+				{ null, null }, // invalid - name can't be null
+				{ "c", true }, // valid
+		};
+		accesses = _utils.createItemAccess(data);
+		_serviceDef = _utils.createServiceDefWithAccessTypes(new String[] { "a", "b", "c", "d" });
+		_failures.clear(); assertFalse(_validator.isValidItemAccesses(accesses, _failures, _serviceDef));
+	}
+	
+	@Test
+	public void test_isValidPolicyItemAccess_happyPath() {
+		
+		RangerPolicyItemAccess access = mock(RangerPolicyItemAccess.class);
+		when(access.getType()).thenReturn("an-Access"); // valid
+
+		Set<String> validAccesses = Sets.newHashSet(new String[] { "an-access", "another-access" });  // valid accesses should be lower-cased
+		
+		// both null or true access types are the same and valid
+		for (Boolean allowed : new Boolean[] { null, true } ) {
+			when(access.getIsAllowed()).thenReturn(allowed);
+			assertTrue(_validator.isValidPolicyItemAccess(access, _failures, validAccesses));
+			assertTrue(_failures.isEmpty());
+		}
+	}
+	
+	@Test
+	public void test_isValidPolicyItemAccess_failures() {
+		
+		Set<String> validAccesses = Sets.newHashSet(new String[] { "anAccess", "anotherAccess" });
+		// null/empty names are invalid
+		RangerPolicyItemAccess access = mock(RangerPolicyItemAccess.class);
+		when(access.getIsAllowed()).thenReturn(null); // valid since null == true
+		for (String type : new String[] { null, " 	"}) {
+			when(access.getType()).thenReturn(type); // invalid
+			// null/empty validAccess set skips all checks
+			assertTrue(_validator.isValidPolicyItemAccess(access, _failures, null));
+			assertTrue(_validator.isValidPolicyItemAccess(access, _failures, new HashSet<String>()));
+			_failures.clear(); assertFalse(_validator.isValidPolicyItemAccess(access, _failures, validAccesses));
+			_utils.checkFailureForMissingValue(_failures, "policy item access type");
+		}
+		
+		when(access.getType()).thenReturn("anAccess"); // valid
+		when(access.getIsAllowed()).thenReturn(false); // invalid
+		_failures.clear();assertFalse(_validator.isValidPolicyItemAccess(access, _failures, validAccesses));
+		_utils.checkFailureForSemanticError(_failures, "policy item access type allowed");
+		
+		when(access.getType()).thenReturn("newAccessType"); // invalid
+		_failures.clear(); assertFalse(_validator.isValidPolicyItemAccess(access, _failures, validAccesses));
+		_utils.checkFailureForSemanticError(_failures, "policy item access type");
+	}
+	
+	final Object[][] resourceDef_happyPath = new Object[][] {
+			// { "resource-name", "isExcludes", "isRecursive" }
+			{ "db", true, true },
+			{ "tbl", null, true },
+			{ "col", true, false },
+	};
+	
+	private Object[][] policyResourceMap_happyPath = new Object[][] {
+			// { "resource-name", "isExcludes", "isRecursive" }
+			{ "db", null, true },    // null should be treated as false
+			{ "tbl", false, false }, // set to false where def is null and def is true  
+			{ "col", true, null}     // set to null where def is false
+	};
+	
+	@Test
+	public final void test_isValidResourceFlags_happyPath() {
+		// passing null values effectively bypasses the filter
+		assertTrue(_validator.isValidResourceFlags(null, _failures, null, "a-service-def", "a-policy"));
+		// so does passing in empty collections
+		Map<String, RangerPolicyResource> resourceMap = _utils.createPolicyResourceMap2(policyResourceMap_happyPath);
+		List<RangerResourceDef> resourceDefs = _utils.createResourceDefs2(resourceDef_happyPath);
+		when(_serviceDef.getResources()).thenReturn(resourceDefs);
+		assertTrue(_validator.isValidResourceFlags(resourceMap, _failures, resourceDefs, "a-service-def", "a-policy"));
+	}
+
+	private Object[][] policyResourceMap_failures = new Object[][] {
+			// { "resource-name", "isExcludes", "isRecursive" }
+			{ "db", true, true },    // ok: def has true for both  
+			{ "tbl", true, null },   // excludes: def==false, policy==true  
+			{ "col", false, true }    // recursive: def==null (i.e. false), policy==true
+	};
+	
+	@Test
+	public final void test_isValidResourceFlags_failures() {
+		// passing true when def says false/null
+		List<RangerResourceDef> resourceDefs = _utils.createResourceDefs2(resourceDef_happyPath);
+		Map<String, RangerPolicyResource> resourceMap = _utils.createPolicyResourceMap2(policyResourceMap_failures);
+		when(_serviceDef.getResources()).thenReturn(resourceDefs);
+		assertFalse(_validator.isValidResourceFlags(resourceMap, _failures, resourceDefs, "a-service-def", "a-policy"));
+		_utils.checkFailureForSemanticError(_failures, "isExcludes", "tbl");
+		_utils.checkFailureForSemanticError(_failures, "isRecursive", "col");
+	}
+
+	private ValidationTestUtils _utils = new ValidationTestUtils();
+	private List<ValidationFailureDetails> _failures = new ArrayList<ValidationFailureDetails>();
+	private ServiceStore _store;
+	private RangerPolicy _policy;
+	private RangerPolicyValidator _validator;
+	private RangerServiceDef _serviceDef;
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerServiceDefValidator.java
----------------------------------------------------------------------
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerServiceDefValidator.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerServiceDefValidator.java
new file mode 100644
index 0000000..1019aa1
--- /dev/null
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerServiceDefValidator.java
@@ -0,0 +1,355 @@
+package org.apache.ranger.plugin.model.validation;
+
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.ranger.plugin.model.RangerServiceDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumElementDef;
+import org.apache.ranger.plugin.model.validation.RangerServiceDefValidator;
+import org.apache.ranger.plugin.model.validation.ValidationFailureDetails;
+import org.apache.ranger.plugin.model.validation.RangerValidator.Action;
+import org.apache.ranger.plugin.store.ServiceStore;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.collect.ImmutableMap;
+
+public class TestRangerServiceDefValidator {
+
+	@Before
+	public void setUp() throws Exception {
+		_store = mock(ServiceStore.class);
+		_validator = new RangerServiceDefValidator(_store);
+		_failures = new ArrayList<ValidationFailureDetails>();
+		_serviceDef = mock(RangerServiceDef.class);
+	}
+
+	final Action[] cu = new Action[] { Action.CREATE, Action.UPDATE };
+	
+	final Object[][] accessTypes_good = new Object[][] {
+			{ "read",  null },                                // ok, null implied grants
+			{ "write", new String[] {   } },                  // ok, empty implied grants
+			{ "admin", new String[] { "READ",  "write" } }    // ok, admin access implies read/write, access types are case-insensitive
+	};
+
+	final Map<String, String[]> enums_good = ImmutableMap.of(
+			"authentication-type", new String[] { "simple", "kerberos" },
+			"time-unit", new String[] { "day", "hour", "minute" }
+	);
+	
+	@Test
+	public final void test_isValid_happyPath_create() throws Exception {
+		
+		// setup access types with implied access and couple of enums
+		List<RangerAccessTypeDef> accessTypeDefs = _utils.createAccessTypeDefs(accessTypes_good);
+		when(_serviceDef.getAccessTypes()).thenReturn(accessTypeDefs);
+		List<RangerEnumDef> enumDefs = _utils.createEnumDefs(enums_good);
+		when(_serviceDef.getEnums()).thenReturn(enumDefs);
+
+		// create: id is not relevant, name should not conflict 
+		when(_serviceDef.getId()).thenReturn(null); // id is not relevant for create
+		when(_serviceDef.getName()).thenReturn("aServiceDef"); // service has a name
+		when(_store.getServiceDefByName("aServiceDef")).thenReturn(null); // no name collision
+		assertTrue(_validator.isValid(_serviceDef, Action.CREATE, _failures));
+		assertTrue(_failures.isEmpty());
+		
+		// update: id should match existing service, name should not point to different service def
+		when(_serviceDef.getId()).thenReturn(5L);
+		RangerServiceDef existingServiceDef = mock(RangerServiceDef.class);
+		when(_store.getServiceDef(5L)).thenReturn(existingServiceDef);
+		assertTrue(_validator.isValid(_serviceDef, Action.UPDATE, _failures));
+		assertTrue(_failures.isEmpty());
+		
+		// update: if name points to a service that it's id should be the same
+		RangerServiceDef anotherExistingServiceDef = mock(RangerServiceDef.class);
+		when(anotherExistingServiceDef.getId()).thenReturn(5L);
+		when(_store.getServiceDefByName("aServiceDef")).thenReturn(anotherExistingServiceDef);
+		assertTrue(_validator.isValid(_serviceDef, Action.UPDATE, _failures));
+		assertTrue(_failures.isEmpty());
+	}
+	
+	@Test
+	public final void testIsValid_Long_failures() throws Exception {
+		Long id = null;
+		// passing in wrong action type 
+		boolean result = _validator.isValid((Long)null, Action.CREATE, _failures);
+		assertFalse(result);
+		_utils.checkFailureForInternalError(_failures);
+		// passing in null id is an error
+		_failures.clear(); assertFalse(_validator.isValid((Long)null, Action.DELETE, _failures));
+		_utils.checkFailureForMissingValue(_failures, "id");
+		// a service def with that id should exist, else it is an error
+		id = 3L;
+		when(_store.getServiceDef(id)).thenReturn(null);
+		_failures.clear(); assertFalse(_validator.isValid(id, Action.DELETE, _failures));
+		_utils.checkFailureForSemanticError(_failures, "id");
+		// happypath
+		when(_store.getServiceDef(id)).thenReturn(_serviceDef);
+		_failures.clear(); assertTrue(_validator.isValid(id, Action.DELETE, _failures));
+		assertTrue(_failures.isEmpty());
+	}
+
+	@Test
+	public final void testIsValid_failures_name() throws Exception {
+		// null service def and bad service def name
+		for (Action action : cu) {
+			// passing in null service def is an error
+			assertFalse(_validator.isValid((RangerServiceDef)null, action, _failures));
+			_utils.checkFailureForMissingValue(_failures, "service def");
+			// name should be valid
+			for (String name : new String[] { null, "", "  " }) {
+				when(_serviceDef.getName()).thenReturn(name);
+				_failures.clear(); assertFalse(_validator.isValid(_serviceDef, action, _failures));
+				_utils.checkFailureForMissingValue(_failures, "name");
+			}
+		}
+	}
+	
+	@Test
+	public final void testIsValid_failures_id() throws Exception {
+		// id is required for update
+		when(_serviceDef.getId()).thenReturn(null);
+		assertFalse(_validator.isValid(_serviceDef, Action.UPDATE, _failures));
+		_utils.checkFailureForMissingValue(_failures, "id");
+		
+		// update: service should exist for the passed in id
+		Long id = 7L;
+		when(_serviceDef.getId()).thenReturn(id);
+		when(_store.getServiceDef(id)).thenReturn(null);
+		assertFalse(_validator.isValid(_serviceDef, Action.UPDATE, _failures));
+		_utils.checkFailureForSemanticError(_failures, "id");
+
+		when(_store.getServiceDef(id)).thenThrow(new Exception());
+		assertFalse(_validator.isValid(_serviceDef, Action.UPDATE, _failures));
+		_utils.checkFailureForSemanticError(_failures, "id");
+	}
+	
+	@Test
+	public final void testIsValid_failures_nameId_create() throws Exception {
+		// service shouldn't exist with the name
+		RangerServiceDef existingServiceDef = mock(RangerServiceDef.class);
+		when(_store.getServiceDefByName("existing-service")).thenReturn(existingServiceDef);
+		when(_serviceDef.getName()).thenReturn("existing-service");
+		_failures.clear(); assertFalse(_validator.isValid(_serviceDef, Action.CREATE, _failures));
+		_utils.checkFailureForSemanticError(_failures, "name");
+	}
+	
+	@Test
+	public final void testIsValid_failures_nameId_update() throws Exception {
+		
+		// update: if service exists with the same name then it can't point to a different service
+		Long id = 7L;
+		when(_serviceDef.getId()).thenReturn(id);
+		RangerServiceDef existingServiceDef = mock(RangerServiceDef.class);
+		when(existingServiceDef.getId()).thenReturn(id);
+		when(_store.getServiceDef(id)).thenReturn(existingServiceDef);
+		
+		String name = "aServiceDef";
+		when(_serviceDef.getName()).thenReturn(name);
+		RangerServiceDef anotherExistingServiceDef = mock(RangerServiceDef.class);
+		Long anotherId = 49L;
+		when(anotherExistingServiceDef.getId()).thenReturn(anotherId);
+		when(_store.getServiceDefByName(name)).thenReturn(anotherExistingServiceDef);
+		
+		assertFalse(_validator.isValid(_serviceDef, Action.UPDATE, _failures));
+		_utils.checkFailureForSemanticError(_failures, "id/name");
+	}
+
+	final Object[][] accessTypes_bad_unknownType = new Object[][] {
+			{ "read",  null },                                // ok, null implied grants
+			{ "write", new String[] {   } },                  // ok, empty implied grants
+			{ "admin", new String[] { "ReaD",  "execute" } }  // non-existent access type (execute), read is good (case should not matter)
+	};
+
+	final Object[][] accessTypes_bad_selfReference = new Object[][] {
+			{ "read",  null },                                // ok, null implied grants
+			{ "write", new String[] {   } },                  // ok, empty implied grants
+			{ "admin", new String[] { "write", "admin" } }  // non-existent access type (execute)
+	};
+
+	@Test
+	public final void test_isValidAccessTypes_happyPath() {
+		List<RangerAccessTypeDef> input = _utils.createAccessTypeDefs(accessTypes_good);
+		assertTrue(_validator.isValidAccessTypes(input, _failures));
+		assertTrue(_failures.isEmpty());
+	}
+	
+	@Test
+	public final void test_isValidAccessTypes_failures() {
+		// sending in empty null access type defs is ok
+		assertTrue(_validator.isValidAccessTypes(null, _failures));
+		assertTrue(_failures.isEmpty());
+		
+		List<RangerAccessTypeDef> input = new ArrayList<RangerAccessTypeDef>();
+		_failures.clear(); assertTrue(_validator.isValidAccessTypes(input, _failures));
+		assertTrue(_failures.isEmpty());
+
+		// null/empty access types
+		List<RangerAccessTypeDef> accessTypeDefs = _utils.createAccessTypeDefs(new String[] { null, "", "		" });
+		_failures.clear(); assertFalse(_validator.isValidAccessTypes(accessTypeDefs, _failures));
+		_utils.checkFailureForMissingValue(_failures, "access type name");
+		
+		// duplicate access types
+		accessTypeDefs = _utils.createAccessTypeDefs(new String[] { "read", "write", "execute", "read" } );
+		_failures.clear(); assertFalse(_validator.isValidAccessTypes(accessTypeDefs, _failures));
+		_utils.checkFailureForSemanticError(_failures, "access type name", "read");
+		
+		// duplicate access types - case-insensitive
+		accessTypeDefs = _utils.createAccessTypeDefs(new String[] { "read", "write", "execute", "READ" } );
+		_failures.clear(); assertFalse(_validator.isValidAccessTypes(accessTypeDefs, _failures));
+		_utils.checkFailureForSemanticError(_failures, "access type name", "READ");
+		
+		// unknown access type in implied grants list
+		accessTypeDefs = _utils.createAccessTypeDefs(accessTypes_bad_unknownType);
+		_failures.clear(); assertFalse(_validator.isValidAccessTypes(accessTypeDefs, _failures));
+		_utils.checkFailureForSemanticError(_failures, "implied grants", "execute");
+		
+		// access type with implied grant referring to itself
+		accessTypeDefs = _utils.createAccessTypeDefs(accessTypes_bad_selfReference);
+		_failures.clear(); assertFalse(_validator.isValidAccessTypes(accessTypeDefs, _failures));
+		_utils.checkFailureForSemanticError(_failures, "implied grants", "admin");
+	}
+	
+	final Map<String, String[]> enums_bad_enumName_null = ImmutableMap.of(
+			"authentication-type", new String[] { "simple", "kerberos" },
+			"time-unit", new String[] { "day", "hour", "minute" },
+			"null", new String[] { "foo", "bar", "tar" } // null enum-name -- "null" is a special value that leads to a null enum name
+	);
+	
+	final Map<String, String[]> enums_bad_enumName_blank = ImmutableMap.of(
+			"authentication-type", new String[] { "simple", "kerberos" },
+			"time-unit", new String[] { "day", "hour", "minute" },
+			"  ", new String[] { "foo", "bar", "tar" } // enum name is all spaces
+	);
+	
+	final Map<String, String[]> enums_bad_Elements_empty = ImmutableMap.of(
+			"authentication-type", new String[] { "simple", "kerberos" },
+			"time-unit", new String[] { "day", "hour", "minute" },
+			"anEnum", new String[] { } // enum elements collection is empty
+	);
+	
+	final Map<String, String[]> enums_bad_enumName_duplicate_exact = ImmutableMap.of(
+			"authentication-type", new String[] { "simple", "kerberos" },
+			"time-unit", new String[] { "day", "hour", "minute" }
+	);
+	
+	final Map<String, String[]> enums_bad_enumName_duplicate_differentCase = ImmutableMap.of(
+			"authentication-type", new String[] { "simple", "kerberos" },
+			"time-unit", new String[] { "day", "hour", "minute" },
+			"Authentication-Type", new String[] { } // duplicate enum-name different in case
+	);
+	
+	@Test
+	public final void test_isValidEnums_happyPath() {
+		List<RangerEnumDef> input = _utils.createEnumDefs(enums_good);
+		assertTrue(_validator.isValidEnums(input, _failures));
+		assertTrue(_failures.isEmpty());
+	}
+	
+	@Test
+	public final void test_isValidEnums_failures() {
+		// null elements in enum def list are a failure
+		List<RangerEnumDef> input = _utils.createEnumDefs(enums_good);
+		input.add(null);
+		assertFalse(_validator.isValidEnums(input, _failures));
+		_utils.checkFailureForMissingValue(_failures, "enum def");
+		
+		// enum names should be valid
+		input = _utils.createEnumDefs(enums_bad_enumName_null);
+		_failures.clear(); assertFalse(_validator.isValidEnums(input, _failures));
+		_utils.checkFailureForMissingValue(_failures, "enum def name");
+
+		input = _utils.createEnumDefs(enums_bad_enumName_blank);
+		_failures.clear(); assertFalse(_validator.isValidEnums(input, _failures));
+		_utils.checkFailureForMissingValue(_failures, "enum def name");
+		
+		// enum elements collection should not be null or empty
+		input = _utils.createEnumDefs(enums_good);
+		RangerEnumDef anEnumDef = mock(RangerEnumDef.class);
+		when(anEnumDef.getName()).thenReturn("anEnum");
+		when(anEnumDef.getElements()).thenReturn(null);
+		input.add(anEnumDef);
+		_failures.clear(); assertFalse(_validator.isValidEnums(input, _failures));
+		_utils.checkFailureForMissingValue(_failures, "enum values", "anEnum");
+
+		input = _utils.createEnumDefs(enums_bad_Elements_empty);
+		_failures.clear(); assertFalse(_validator.isValidEnums(input, _failures));
+		_utils.checkFailureForMissingValue(_failures, "enum values", "anEnum");
+	
+		// enum names should be distinct -- exact match
+		input = _utils.createEnumDefs(enums_good);
+		// add an element with same name as the first element
+		String name = input.iterator().next().getName();
+		when(anEnumDef.getName()).thenReturn(name);
+		List<RangerEnumElementDef> elementDefs = _utils.createEnumElementDefs(new String[] {"val1", "val2"}); 
+		when(anEnumDef.getElements()).thenReturn(elementDefs);
+		input.add(anEnumDef);
+		_failures.clear(); assertFalse(_validator.isValidEnums(input, _failures));
+		_utils.checkFailureForSemanticError(_failures, "enum def name", name);
+
+		// enum names should be distinct -- case insensitive
+		input = _utils.createEnumDefs(enums_bad_enumName_duplicate_differentCase);
+		_failures.clear(); assertFalse(_validator.isValidEnums(input, _failures));
+		_utils.checkFailureForSemanticError(_failures, "enum def name", "Authentication-Type");
+	
+		// enum default index should be right
+		input = _utils.createEnumDefs(enums_good);
+		// set the index of 1st on to be less than 0
+		when(input.iterator().next().getDefaultIndex()).thenReturn(-1);
+		_failures.clear(); assertFalse(_validator.isValidEnums(input, _failures));
+		_utils.checkFailureForSemanticError(_failures, "enum default index", "authentication-type");
+		// set the index to be more than number of elements
+		when(input.iterator().next().getDefaultIndex()).thenReturn(2);
+		_failures.clear(); assertFalse(_validator.isValidEnums(input, _failures));
+		_utils.checkFailureForSemanticError(_failures, "enum default index", "authentication-type");
+	}
+
+	@Test
+	public final void test_isValidEnumElements_happyPath() {
+		List<RangerEnumElementDef> input = _utils.createEnumElementDefs(new String[] { "simple", "kerberos" });
+		assertTrue(_validator.isValidEnumElements(input, _failures, "anEnum"));
+		assertTrue(_failures.isEmpty());
+	}
+
+	@Test
+	public final void test_isValidEnumElements_failures() {
+		// enum element collection should not have nulls in it
+		List<RangerEnumElementDef> input = _utils.createEnumElementDefs(new String[] { "simple", "kerberos" });
+		input.add(null);
+		assertFalse(_validator.isValidEnumElements(input, _failures, "anEnum"));
+		_utils.checkFailureForMissingValue(_failures, "enum element", "anEnum");
+
+		// element names can't be null/empty
+		input = _utils.createEnumElementDefs(new String[] { "simple", "kerberos", null });
+		_failures.clear(); assertFalse(_validator.isValidEnumElements(input, _failures, "anEnum"));
+		_utils.checkFailureForMissingValue(_failures, "enum element name", "anEnum");
+
+		input = _utils.createEnumElementDefs(new String[] { "simple", "kerberos", "		" }); // two tabs
+		_failures.clear(); assertFalse(_validator.isValidEnumElements(input, _failures, "anEnum"));
+		_utils.checkFailureForMissingValue(_failures, "enum element name", "anEnum");
+		
+		// element names should be distinct - case insensitive
+		input = _utils.createEnumElementDefs(new String[] { "simple", "kerberos", "kerberos" }); // duplicate name - exact match
+		_failures.clear(); assertFalse(_validator.isValidEnumElements(input, _failures, "anEnum"));
+		_utils.checkFailureForSemanticError(_failures, "enum element name", "anEnum");
+		
+		input = _utils.createEnumElementDefs(new String[] { "simple", "kerberos", "kErbErOs" }); // duplicate name - different case
+		_failures.clear(); assertFalse(_validator.isValidEnumElements(input, _failures, "anEnum"));
+		_utils.checkFailureForSemanticError(_failures, "enum element name", "anEnum");
+	}
+	
+	private ValidationTestUtils _utils = new ValidationTestUtils();
+	RangerServiceDef _serviceDef;
+	List<ValidationFailureDetails> _failures;
+	ServiceStore _store;
+	RangerServiceDefValidator _validator;
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerServiceValidator.java
----------------------------------------------------------------------
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerServiceValidator.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerServiceValidator.java
new file mode 100644
index 0000000..dd8485e
--- /dev/null
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerServiceValidator.java
@@ -0,0 +1,240 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF 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.apache.ranger.plugin.model.validation;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.ranger.plugin.model.RangerService;
+import org.apache.ranger.plugin.model.RangerServiceDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerServiceConfigDef;
+import org.apache.ranger.plugin.model.validation.RangerServiceValidator;
+import org.apache.ranger.plugin.model.validation.ValidationFailureDetails;
+import org.apache.ranger.plugin.model.validation.RangerValidator.Action;
+import org.apache.ranger.plugin.store.ServiceStore;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TestRangerServiceValidator {
+	
+	final Action[] cud = new Action[] { Action.CREATE, Action.UPDATE, Action.DELETE };
+	final Action[] cu = new Action[] { Action.CREATE, Action.UPDATE };
+	final Action[] ud = new Action[] { Action.UPDATE, Action.DELETE };
+
+	@Before
+	public void before() {
+		_store = mock(ServiceStore.class);
+		_action = Action.CREATE; // by default we set action to create
+		_validator = new RangerServiceValidator(_store);
+	}
+
+	void checkFailure_isValid(RangerServiceValidator validator, RangerService service, Action action, List<ValidationFailureDetails> failures, String errorType, String field) {
+		checkFailure_isValid(validator, service, action, failures, errorType, field, null);
+	}
+	
+	void checkFailure_isValid(RangerServiceValidator validator, RangerService service, Action action, List<ValidationFailureDetails> failures, String errorType, String field, String subField) {
+		failures.clear();
+		assertFalse(validator.isValid(service, action, failures));
+		switch (errorType) {
+		case "missing":
+			_utils.checkFailureForMissingValue(failures, field, subField);
+			break;
+		case "semantic":
+			_utils.checkFailureForSemanticError(failures, field, subField);
+			break;
+		case "internal error":
+			_utils.checkFailureForInternalError(failures);
+			break;
+		default:
+			fail("Unsupported errorType[" + errorType + "]");
+			break;
+		}
+	}
+	
+	@Test
+	public void testIsValid_failures() throws Exception {
+		RangerService service = mock(RangerService.class);
+		// passing in a null service to the check itself is an error
+		assertFalse(_validator.isValid((RangerService)null, _action, _failures));
+		_utils.checkFailureForMissingValue(_failures, "service");
+
+		// id is required for update
+		when(service.getId()).thenReturn(null);
+		// let's verify the failure and the sort of error information that is returned (for one of these)
+		// assert that among the failure reason is one about id being missing.
+		checkFailure_isValid(_validator, service, Action.UPDATE, _failures, "missing", "id");
+		when(service.getId()).thenReturn(7L);
+
+		for (Action action : cu) {
+			// null, empty of blank name renders a service invalid
+			for (String name : new String[] { null, "", " 	" }) { // spaces and tabs
+				when(service.getName()).thenReturn(name);
+				checkFailure_isValid(_validator, service, action, _failures, "missing", "name");
+			}
+			// same is true for the type
+			for (String type : new String[] { null, "", "    " }) {
+				when(service.getType()).thenReturn(type);
+				checkFailure_isValid(_validator, service, action, _failures, "missing", "type");
+			}
+		}
+		when(service.getName()).thenReturn("aName");
+
+		// if non-empty, then the type should exist!
+		when(_store.getServiceDefByName("null-type")).thenReturn(null);
+		when(_store.getServiceDefByName("throwing-type")).thenThrow(new Exception());
+		for (Action action : cu) {
+			for (String type : new String[] { "null-type", "throwing-type" }) {
+				when(service.getType()).thenReturn(type);
+				checkFailure_isValid(_validator, service, action, _failures, "semantic", "type");
+			}
+		}
+		when(service.getType()).thenReturn("aType");
+		RangerServiceDef serviceDef = mock(RangerServiceDef.class);
+		when(_store.getServiceDefByName("aType")).thenReturn(serviceDef);
+		
+		// Create: No service should exist matching its id and/or name
+		RangerService anExistingService = mock(RangerService.class);
+		when(_store.getServiceByName("aName")).thenReturn(anExistingService);
+		checkFailure_isValid(_validator, service, Action.CREATE, _failures, "semantic", "name");
+
+		// Update: service should exist matching its id and name specified should not belong to a different service
+		when(_store.getService(7L)).thenReturn(null);
+		when(_store.getServiceByName("aName")).thenReturn(anExistingService);
+		checkFailure_isValid(_validator, service, Action.UPDATE, _failures, "semantic", "id");
+
+		when(_store.getService(7L)).thenReturn(anExistingService);
+		RangerService anotherExistingService = mock(RangerService.class);
+		when(anotherExistingService.getId()).thenReturn(49L);
+		when(_store.getServiceByName("aName")).thenReturn(anotherExistingService);
+		checkFailure_isValid(_validator, service, Action.UPDATE, _failures, "semantic", "id/name");
+	}
+	
+	@Test
+	public void test_isValid_missingRequiredParameter() throws Exception {
+		// Create/Update: simulate a condition where required parameters are missing
+		Object[][] input = new Object[][] {
+				{ "param1", true },
+				{ "param2", true },
+				{ "param3", false },
+				{ "param4", false },
+		};
+		List<RangerServiceConfigDef> configDefs = _utils.createServiceConditionDefs(input);
+		RangerServiceDef serviceDef = mock(RangerServiceDef.class);
+		when(serviceDef.getConfigs()).thenReturn(configDefs);
+		// wire this service def into store
+		when(_store.getServiceDefByName("aType")).thenReturn(serviceDef);
+		// create a service with some require parameters missing
+		RangerService service = mock(RangerService.class);
+		when(service.getType()).thenReturn("aType");
+		when(service.getName()).thenReturn("aName");
+		// required parameters param2 is missing
+		String[] params = new String[] { "param1", "param3", "param4", "param5" };
+		Map<String, String> paramMap = _utils.createMap(params);
+		when(service.getConfigs()).thenReturn(paramMap);
+		// service does not exist in the store
+		when(_store.getServiceByName("aService")).thenReturn(null);
+		for (Action action : cu) {
+			// it should be invalid
+			checkFailure_isValid(_validator, service, action, _failures, "missing", "configuration", "param2");
+		}
+	}
+
+	@Test
+	public void test_isValid_happyPath() throws Exception {
+		// create a service def with some required parameters 
+		Object[][] serviceDefInput = new Object[][] {
+				{ "param1", true },
+				{ "param2", true },
+				{ "param3", false },
+				{ "param4", false },
+				{ "param5", true },
+		};
+		List<RangerServiceConfigDef> configDefs = _utils.createServiceConditionDefs(serviceDefInput);
+		RangerServiceDef serviceDef = mock(RangerServiceDef.class);
+		when(serviceDef.getConfigs()).thenReturn(configDefs);
+		// create a service with some parameters on it
+		RangerService service = mock(RangerService.class);
+		when(service.getName()).thenReturn("aName");
+		when(service.getType()).thenReturn("aType");
+		// contains an extra parameter (param6) and one optional is missing(param4)
+		String[] configs = new String[] { "param1", "param2", "param3", "param5", "param6" };
+		Map<String, String> configMap = _utils.createMap(configs);  
+		when(service.getConfigs()).thenReturn(configMap);
+		// wire then into the store
+		// service does not exists
+		when(_store.getServiceByName("aName")).thenReturn(null);
+		// service def exists
+		when(_store.getServiceDefByName("aType")).thenReturn(serviceDef);
+
+		assertTrue(_validator.isValid(service, Action.CREATE, _failures));
+
+		// for update to work the only additional requirement is that id is required and service should exist
+		// if name is not null and it points to a service then it should match the id
+		when(service.getId()).thenReturn(7L);
+		RangerService existingService = mock(RangerService.class);
+		when(existingService.getId()).thenReturn(7L);
+		when(_store.getService(7L)).thenReturn(existingService);
+		when(_store.getServiceByName("aName")).thenReturn(existingService);
+		assertTrue(_validator.isValid(service, Action.UPDATE, _failures));
+		// name need not point to a service for update to work, of course.
+		when(_store.getServiceByName("aName")).thenReturn(null);
+		assertTrue(_validator.isValid(service, Action.UPDATE, _failures));
+	}
+
+	@Test
+	public void test_isValid_withId_errorConditions() throws Exception {
+		// api that takes in long is only supported for delete currently
+		assertFalse(_validator.isValid(1L, Action.CREATE, _failures));
+		_utils.checkFailureForInternalError(_failures);
+		// passing in a null id is a failure!
+		_validator = new RangerServiceValidator(_store);
+		_failures.clear(); assertFalse(_validator.isValid((Long)null, Action.DELETE, _failures));
+		_utils.checkFailureForMissingValue(_failures, "id");
+		// if service with that id does not exist then that, too, is a failure
+		when(_store.getService(1L)).thenReturn(null);
+		when(_store.getService(2L)).thenThrow(new Exception());
+		_failures.clear(); assertFalse(_validator.isValid(1L, Action.DELETE, _failures));
+		_utils.checkFailureForSemanticError(_failures, "id");
+
+		_failures.clear(); assertFalse(_validator.isValid(2L, Action.DELETE, _failures));
+		_utils.checkFailureForSemanticError(_failures, "id");
+	}
+	
+	@Test
+	public void test_isValid_withId_happyPath() throws Exception {
+		_validator = new RangerServiceValidator(_store);
+		RangerService service = mock(RangerService.class);
+		when(_store.getService(1L)).thenReturn(service);
+		assertTrue(_validator.isValid(1L, Action.DELETE, _failures));
+	}
+	
+	private ServiceStore _store;
+	private RangerServiceValidator _validator;
+	private Action _action;
+	private ValidationTestUtils _utils = new ValidationTestUtils();
+	private List<ValidationFailureDetails> _failures = new ArrayList<ValidationFailureDetails>();
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerValidator.java
----------------------------------------------------------------------
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerValidator.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerValidator.java
new file mode 100644
index 0000000..f17b2c2
--- /dev/null
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerValidator.java
@@ -0,0 +1,476 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF 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.apache.ranger.plugin.model.validation;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.ranger.plugin.model.RangerPolicy;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
+import org.apache.ranger.plugin.model.RangerService;
+import org.apache.ranger.plugin.model.RangerServiceDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerServiceConfigDef;
+import org.apache.ranger.plugin.model.validation.RangerValidator;
+import org.apache.ranger.plugin.model.validation.RangerValidator.Action;
+import org.apache.ranger.plugin.store.ServiceStore;
+import org.apache.ranger.plugin.util.SearchFilter;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.collect.Maps;
+
+public class TestRangerValidator {
+
+	static class RangerValidatorForTest extends RangerValidator {
+
+		public RangerValidatorForTest(ServiceStore store) {
+			super(store);
+		}
+		
+		boolean isValid(String behavior) {
+			boolean valid;
+			if (behavior.equals("valid")) {
+				valid = true;
+			} else {
+				valid = false;
+			}
+			return valid;
+		}
+	}
+	
+	@Before
+	public void before() {
+		_store = mock(ServiceStore.class);
+		_validator = new RangerValidatorForTest(_store);
+	}
+
+	@Test
+	public void test_ctor_firewalling() {
+		try {
+			// service store can't be null during construction  
+			new RangerValidatorForTest(null);
+			fail("Should have thrown exception!");
+		} catch (IllegalArgumentException e) {
+			// expected exception
+		}
+	}
+	
+	@Test
+	public void test_validate() {
+		// default implementation should fail.  This is abstract class.  Sub-class must do something sensible with isValid
+		try {
+			_validator.validate(1L, Action.CREATE);
+			fail("Should have thrown exception!");
+		} catch (Exception e) {
+			// ok expected exception
+			String message = e.getMessage();
+			assertTrue(message.contains("internal error"));
+		}
+	}
+
+	@Test
+	public void test_getServiceConfigParameters() {
+		// reasonable protection against null values
+		Set<String> parameters = _validator.getServiceConfigParameters(null);
+		assertNotNull(parameters);
+		assertTrue(parameters.isEmpty());
+		
+		RangerService service = mock(RangerService.class);
+		when(service.getConfigs()).thenReturn(null);
+		parameters = _validator.getServiceConfigParameters(service);
+		assertNotNull(parameters);
+		assertTrue(parameters.isEmpty());
+		
+		when(service.getConfigs()).thenReturn(new HashMap<String, String>());
+		parameters = _validator.getServiceConfigParameters(service);
+		assertNotNull(parameters);
+		assertTrue(parameters.isEmpty());
+
+		String[] keys = new String[] { "a", "b", "c" };
+		Map<String, String> map = _utils.createMap(keys);
+		when(service.getConfigs()).thenReturn(map);
+		parameters = _validator.getServiceConfigParameters(service);
+		for (String key: keys) {
+			assertTrue("key", parameters.contains(key));
+		}
+	}
+	
+	@Test
+	public void test_getRequiredParameters() {
+		// reasonable protection against null things
+		Set<String> parameters = _validator.getRequiredParameters(null);
+		assertNotNull(parameters);
+		assertTrue(parameters.isEmpty());
+
+		RangerServiceDef serviceDef = mock(RangerServiceDef.class);
+		when(serviceDef.getConfigs()).thenReturn(null);
+		parameters = _validator.getRequiredParameters(null);
+		assertNotNull(parameters);
+		assertTrue(parameters.isEmpty());
+
+		List<RangerServiceConfigDef> configs = new ArrayList<RangerServiceDef.RangerServiceConfigDef>();
+		when(serviceDef.getConfigs()).thenReturn(configs);
+		parameters = _validator.getRequiredParameters(null);
+		assertNotNull(parameters);
+		assertTrue(parameters.isEmpty());
+		
+		Object[][] input = new Object[][] {
+				{ "param1", false },
+				{ "param2", true },
+				{ "param3", true },
+				{ "param4", false },
+		};
+		configs = _utils.createServiceConditionDefs(input);
+		when(serviceDef.getConfigs()).thenReturn(configs);
+		parameters = _validator.getRequiredParameters(serviceDef);
+		assertTrue("result does not contain: param2", parameters.contains("param2"));
+		assertTrue("result does not contain: param3", parameters.contains("param3"));
+	}
+	
+	@Test
+	public void test_getServiceDef() {
+		try {
+			// if service store returns null or throws an exception then service is deemed invalid
+			when(_store.getServiceDefByName("return null")).thenReturn(null);
+			when(_store.getServiceDefByName("throw")).thenThrow(new Exception());
+			RangerServiceDef serviceDef = mock(RangerServiceDef.class);
+			when(_store.getServiceDefByName("good-service")).thenReturn(serviceDef);
+		} catch (Exception e) {
+			e.printStackTrace();
+			fail("Unexpected exception during mocking!");
+		}
+		
+		assertNull(_validator.getServiceDef("return null"));
+		assertNull(_validator.getServiceDef("throw"));
+		assertFalse(_validator.getServiceDef("good-service") == null);
+	}
+
+	@Test
+	public void test_getPolicy() throws Exception {
+		// if service store returns null or throws an exception then return null policy
+		when(_store.getPolicy(1L)).thenReturn(null);
+		when(_store.getPolicy(2L)).thenThrow(new Exception());
+		RangerPolicy policy = mock(RangerPolicy.class);
+		when(_store.getPolicy(3L)).thenReturn(policy);
+		
+		assertNull(_validator.getPolicy(1L));
+		assertNull(_validator.getPolicy(2L));
+		assertTrue(_validator.getPolicy(3L) != null);
+	}
+
+	@Test
+	public void test_getService_byId() throws Exception {
+		// if service store returns null or throws an exception then service is deemed invalid
+		when(_store.getService(1L)).thenReturn(null);
+		when(_store.getService(2L)).thenThrow(new Exception());
+		RangerService service = mock(RangerService.class);
+		when(_store.getService(3L)).thenReturn(service);
+		
+		assertNull(_validator.getService(1L));
+		assertNull(_validator.getService(2L));
+		assertTrue(_validator.getService(3L) != null);
+	}
+
+	@Test
+	public void test_getService() {
+		try {
+			// if service store returns null or throws an exception then service is deemed invalid
+			when(_store.getServiceByName("return null")).thenReturn(null);
+			when(_store.getServiceByName("throw")).thenThrow(new Exception());
+			RangerService service = mock(RangerService.class);
+			when(_store.getServiceByName("good-service")).thenReturn(service);
+		} catch (Exception e) {
+			e.printStackTrace();
+			fail("Unexpected exception during mocking!");
+		}
+		
+		assertNull(_validator.getService("return null"));
+		assertNull(_validator.getService("throw"));
+		assertFalse(_validator.getService("good-service") == null);
+	}
+	
+	@Test
+	public void test_getAccessTypes() {
+		// passing in null service def
+		Set<String> accessTypes = _validator.getAccessTypes((RangerServiceDef)null);
+		assertTrue(accessTypes.isEmpty());
+		// that has null or empty access type def
+		RangerServiceDef serviceDef = mock(RangerServiceDef.class);
+		when(serviceDef.getAccessTypes()).thenReturn(null);
+		accessTypes = _validator.getAccessTypes(serviceDef);
+		assertTrue(accessTypes.isEmpty());
+
+		List<RangerAccessTypeDef> accessTypeDefs = new ArrayList<RangerServiceDef.RangerAccessTypeDef>();
+		when(serviceDef.getAccessTypes()).thenReturn(accessTypeDefs);
+		accessTypes = _validator.getAccessTypes(serviceDef);
+		assertTrue(accessTypes.isEmpty());
+		
+		// having null accesstypedefs
+		accessTypeDefs.add(null);
+		accessTypes = _validator.getAccessTypes(serviceDef);
+		assertTrue(accessTypes.isEmpty());
+		
+		// access type defs with null empty blank names are skipped, spaces within names are preserved
+		String[] names = new String[] { null, "", "a", "  ", "b ", "		", " C", "	D	" };
+		accessTypeDefs.addAll(_utils.createAccessTypeDefs(names));
+		accessTypes = _validator.getAccessTypes(serviceDef);
+		assertEquals(4, accessTypes.size());
+		assertTrue(accessTypes.contains("a"));
+		assertTrue(accessTypes.contains("b "));
+		assertTrue(accessTypes.contains(" c"));
+		assertTrue(accessTypes.contains("	d	"));
+	}
+	
+	@Test
+	public void test_getResourceNames() {
+		// passing in null service def
+		Set<String> accessTypes = _validator.getMandatoryResourceNames((RangerServiceDef)null);
+		assertTrue(accessTypes.isEmpty());
+		// that has null or empty access type def
+		RangerServiceDef serviceDef = mock(RangerServiceDef.class);
+		when(serviceDef.getResources()).thenReturn(null);
+		accessTypes = _validator.getMandatoryResourceNames(serviceDef);
+		assertTrue(accessTypes.isEmpty());
+
+		List<RangerResourceDef> resourceDefs = new ArrayList<RangerResourceDef>();
+		when(serviceDef.getResources()).thenReturn(resourceDefs);
+		accessTypes = _validator.getMandatoryResourceNames(serviceDef);
+		assertTrue(accessTypes.isEmpty());
+		
+		// having null accesstypedefs
+		resourceDefs.add(null);
+		accessTypes = _validator.getMandatoryResourceNames(serviceDef);
+		assertTrue(accessTypes.isEmpty());
+		
+		// access type defs with null empty blank names are skipped, spaces within names are preserved
+		Object[][] data = {
+				{ "a", true },  // all good
+				null,           // this should put a null element in the resource def!
+				{ "b", null },  // mandatory field is null, i.e. false
+				{ "c", false }, // non-mandatory field false - upper case
+				{ "D", true },  // resource specified in upper case
+				{ "E", false }, // all good
+		};
+		resourceDefs.addAll(_utils.createResourceDefs(data));
+		accessTypes = _validator.getMandatoryResourceNames(serviceDef);
+		assertEquals(2, accessTypes.size());
+		assertTrue(accessTypes.contains("a"));
+		assertTrue(accessTypes.contains("d")); // name should come back lower case
+		
+		accessTypes = _validator.getAllResourceNames(serviceDef);
+		assertEquals(5, accessTypes.size());
+		assertTrue(accessTypes.contains("b"));
+		assertTrue(accessTypes.contains("c"));
+		assertTrue(accessTypes.contains("e"));
+	}
+
+	@Test
+	public void test_getValidationRegExes() {
+		// passing in null service def
+		Map<String, String> regExMap = _validator.getValidationRegExes((RangerServiceDef)null);
+		assertTrue(regExMap.isEmpty());
+		// that has null or empty access type def
+		RangerServiceDef serviceDef = mock(RangerServiceDef.class);
+		when(serviceDef.getResources()).thenReturn(null);
+		regExMap = _validator.getValidationRegExes(serviceDef);
+		assertTrue(regExMap.isEmpty());
+
+		List<RangerResourceDef> resourceDefs = new ArrayList<RangerResourceDef>();
+		when(serviceDef.getResources()).thenReturn(resourceDefs);
+		regExMap = _validator.getValidationRegExes(serviceDef);
+		assertTrue(regExMap.isEmpty());
+		
+		// having null accesstypedefs
+		resourceDefs.add(null);
+		regExMap = _validator.getValidationRegExes(serviceDef);
+		assertTrue(regExMap.isEmpty());
+		
+		// access type defs with null empty blank names are skipped, spaces within names are preserved
+		String[][] data = {
+				{ "a", null },     // null-regex
+				null,              // this should put a null element in the resource def!
+				{ "b", "regex1" }, // valid
+				{ "c", "" },       // empty regex
+				{ "d", "regex2" }, // valid
+				{ "e", "   " },    // blank regex
+				{ "f", "regex3" }, // all good
+		};
+		resourceDefs.addAll(_utils.createResourceDefsWithRegEx(data));
+		regExMap = _validator.getValidationRegExes(serviceDef);
+		assertEquals(3, regExMap.size());
+		assertEquals("regex1", regExMap.get("b"));
+		assertEquals("regex2", regExMap.get("d"));
+		assertEquals("regex3", regExMap.get("f"));
+	}
+
+	@Test
+	public void test_getPolicyResources() {
+		
+		Set<String> result;
+		RangerPolicy policy = null;
+		// null policy
+		result = _validator.getPolicyResources(null);
+		assertTrue(result != null);
+		assertTrue(result.isEmpty());
+		// null resource map
+		policy = mock(RangerPolicy.class);
+		when(policy.getResources()).thenReturn(null);
+		result = _validator.getPolicyResources(null);
+		assertTrue(result != null);
+		assertTrue(result.isEmpty());
+		// empty resource map
+		Map<String, RangerPolicyResource> input = Maps.newHashMap();
+		when(policy.getResources()).thenReturn(input);
+		result = _validator.getPolicyResources(policy);
+		assertTrue(result != null);
+		assertTrue(result.isEmpty());
+		// known resource map
+		input.put("r1", mock(RangerPolicyResource.class));
+		input.put("R2", mock(RangerPolicyResource.class));
+		result = _validator.getPolicyResources(policy);
+		assertEquals(2, result.size());
+		assertTrue("r1", result.contains("r1"));
+		assertTrue("R2", result.contains("r2")); // result should lowercase the resource-names
+	}
+
+	@Test
+	public void test_getIsAuditEnabled() {
+		// null policy
+		RangerPolicy policy = null;
+		boolean result = _validator.getIsAuditEnabled(policy);
+		assertFalse(result);
+		// null isAuditEnabled Boolean is supposed to be TRUE!!
+		policy = mock(RangerPolicy.class);
+		when(policy.getIsAuditEnabled()).thenReturn(null);
+		result = _validator.getIsAuditEnabled(policy);
+		assertTrue(result);
+		// non-null value
+		when(policy.getIsAuditEnabled()).thenReturn(Boolean.FALSE);
+		result = _validator.getIsAuditEnabled(policy);
+		assertFalse(result);
+
+		when(policy.getIsAuditEnabled()).thenReturn(Boolean.TRUE);
+		result = _validator.getIsAuditEnabled(policy);
+		assertTrue(result);
+	}
+
+	@Test
+	public void test_getPolicies() throws Exception {
+
+		// returns null when store returns null
+		String policyName = "aPolicy";
+		String serviceName = "aService";
+		SearchFilter filter = new SearchFilter();
+		filter.setParam(SearchFilter.POLICY_NAME, policyName);
+		filter.setParam(SearchFilter.SERVICE_NAME, serviceName);
+		
+		when(_store.getPolicies(filter)).thenReturn(null);
+		List<RangerPolicy> result = _validator.getPolicies(policyName, serviceName);
+		// validate store is queried with both parameters
+		verify(_store).getPolicies(filter);
+		assertNull(result);
+
+		// returns null if store throws an exception
+		when(_store.getPolicies(filter)).thenThrow(new Exception());
+		result = _validator.getPolicies(policyName, serviceName);
+		assertNull(result);
+	}
+	
+	@Test
+	public void test_getServiceDef_byId() throws Exception {
+		// if service store returns null or throws an exception then service is deemed invalid
+		when(_store.getServiceDef(1L)).thenReturn(null);
+		when(_store.getServiceDef(2L)).thenThrow(new Exception());
+		RangerServiceDef serviceDef = mock(RangerServiceDef.class);
+		when(_store.getServiceDef(3L)).thenReturn(serviceDef);
+		
+		assertNull(_validator.getServiceDef(1L));
+		assertNull(_validator.getServiceDef(2L));
+		assertTrue(_validator.getServiceDef(3L) != null);
+	}
+
+	@Test
+	public void test_getEnumDefaultIndex() {
+		RangerEnumDef enumDef = mock(RangerEnumDef.class);
+		assertEquals(-1, _validator.getEnumDefaultIndex(null));
+		when(enumDef.getDefaultIndex()).thenReturn(null);
+		assertEquals(0, _validator.getEnumDefaultIndex(enumDef));
+		when(enumDef.getDefaultIndex()).thenReturn(-5);
+		assertEquals(-5, _validator.getEnumDefaultIndex(enumDef));
+	}
+	
+	@Test
+	public void test_getImpliedGrants() {
+		
+		// passing in null gets back a null
+		Collection<String> result = _validator.getImpliedGrants(null);
+		assertNull(result);
+		
+		// null or empty implied grant collection gets back an empty collection
+		RangerAccessTypeDef accessTypeDef = mock(RangerAccessTypeDef.class);
+		when(accessTypeDef.getImpliedGrants()).thenReturn(null);
+		result = _validator.getImpliedGrants(accessTypeDef);
+		assertTrue(result.isEmpty());
+		
+		List<String> impliedGrants = new ArrayList<String>();
+		when(accessTypeDef.getImpliedGrants()).thenReturn(impliedGrants);
+		result = _validator.getImpliedGrants(accessTypeDef);
+		assertTrue(result.isEmpty());
+
+		// null/empty values come back as is
+		impliedGrants = Arrays.asList(new String[] { null, "", " ", "		" });
+		when(accessTypeDef.getImpliedGrants()).thenReturn(impliedGrants);
+		result = _validator.getImpliedGrants(accessTypeDef);
+		assertEquals(4, result.size());
+		
+		// non-empty values get lower cased
+		impliedGrants = Arrays.asList(new String[] { "a", "B", "C	", " d " });
+		when(accessTypeDef.getImpliedGrants()).thenReturn(impliedGrants);
+		result = _validator.getImpliedGrants(accessTypeDef);
+		assertEquals(4, result.size());
+		assertTrue(result.contains("a"));
+		assertTrue(result.contains("b"));
+		assertTrue(result.contains("c	"));
+		assertTrue(result.contains(" d "));
+	}
+	
+	private RangerValidatorForTest _validator;
+	private ServiceStore _store;
+	private ValidationTestUtils _utils = new ValidationTestUtils();
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/ValidationTestUtils.java
----------------------------------------------------------------------
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/ValidationTestUtils.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/ValidationTestUtils.java
new file mode 100644
index 0000000..5ed2691
--- /dev/null
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/ValidationTestUtils.java
@@ -0,0 +1,371 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF 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.apache.ranger.plugin.model.validation;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItem;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemAccess;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
+import org.apache.ranger.plugin.model.RangerServiceDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumElementDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerServiceConfigDef;
+import org.apache.ranger.plugin.model.validation.ValidationFailureDetails;
+
+public class ValidationTestUtils {
+	
+	Map<String, String> createMap(String[] keys) {
+		Map<String, String> result = new HashMap<String, String>();
+		for (String key : keys) {
+			result.put(key, "valueof-" + key);
+		}
+		return result;
+	}
+
+	// helper methods for tests
+	List<RangerServiceConfigDef> createServiceConditionDefs(Object[][] input) {
+		List<RangerServiceConfigDef> result = new ArrayList<RangerServiceDef.RangerServiceConfigDef>();
+		
+		for (Object data[] : input) {
+			RangerServiceConfigDef aConfigDef = mock(RangerServiceConfigDef.class);
+			when(aConfigDef.getName()).thenReturn((String)data[0]);
+			when(aConfigDef.getMandatory()).thenReturn((boolean)data[1]);
+			result.add(aConfigDef);
+		}
+		
+		return result;
+	}
+	
+	void checkFailureForSemanticError(List<ValidationFailureDetails> failures, String fieldName) {
+		checkFailure(failures, null, null, true, fieldName, null);
+	}
+
+	void checkFailureForSemanticError(List<ValidationFailureDetails> failures, String fieldName, String subField) {
+		checkFailure(failures, null, null, true, fieldName, subField);
+	}
+
+	void checkFailureForMissingValue(List<ValidationFailureDetails> failures, String field) {
+		checkFailure(failures, null, true, null, field, null);
+	}
+
+	void checkFailureForMissingValue(List<ValidationFailureDetails> failures, String field, String subField) {
+		checkFailure(failures, null, true, null, field, subField);
+	}
+
+	void checkFailureForInternalError(List<ValidationFailureDetails> failures, String fieldName) {
+		checkFailure(failures, true, null, null, fieldName, null);
+	}
+
+	void checkFailureForInternalError(List<ValidationFailureDetails> failures) {
+		checkFailure(failures, true, null, null, null, null);
+	}
+
+	void checkFailure(List<ValidationFailureDetails> failures, Boolean internalError, Boolean missing, Boolean semanticError, String field, String subField) {
+		if (CollectionUtils.isEmpty(failures)) {
+			fail("List of failures is null/empty!");
+		} else {
+			boolean found = false;
+			for (ValidationFailureDetails f : failures) {
+				if ((internalError == null || internalError == f._internalError) &&
+						(missing == null || missing == f._missing) &&
+						(semanticError == null || semanticError == f._semanticError) &&
+						(field == null || field.equals(f._fieldName)) &&
+						(subField == null || subField.equals(f._subFieldName))) {
+					found = true;
+				}
+			}
+			assertTrue(found);
+		}
+	}
+
+	List<RangerAccessTypeDef> createAccessTypeDefs(String[] names) {
+		assertFalse(names == null); // fail if null is passed in!
+		List<RangerAccessTypeDef> defs = new ArrayList<RangerServiceDef.RangerAccessTypeDef>();
+		for (String name : names) {
+			RangerAccessTypeDef def = mock(RangerAccessTypeDef.class);
+			when(def.getName()).thenReturn(name);
+			defs.add(def);
+		}
+		return defs;
+	}
+
+
+	List<RangerAccessTypeDef> createAccessTypeDefs(Object[][] data) {
+		if (data == null) {
+			return null;
+		}
+		List<RangerAccessTypeDef> result = new ArrayList<RangerAccessTypeDef>();
+		if (data.length == 0) {
+			return result;
+		}
+		for (Object[] entry : data) {
+			String accessType = (String)entry[0];
+			String[] impliedAccessArray = (String[])entry[1];
+			List<String> impliedAccesses = null;
+			if (impliedAccessArray != null) {
+				impliedAccesses = Arrays.asList(impliedAccessArray);
+			}
+			RangerAccessTypeDef aTypeDef = mock(RangerAccessTypeDef.class);
+			when(aTypeDef.getName()).thenReturn(accessType);
+			when(aTypeDef.getImpliedGrants()).thenReturn(impliedAccesses);
+			result.add(aTypeDef);
+		}
+		return result;
+	}
+
+	RangerServiceDef createServiceDefWithAccessTypes(String[] accesses) {
+		RangerServiceDef serviceDef = mock(RangerServiceDef.class);
+		List<RangerAccessTypeDef> accessTypeDefs = new ArrayList<RangerServiceDef.RangerAccessTypeDef>();
+		for (String access : accesses) {
+			RangerAccessTypeDef accessTypeDef = mock(RangerAccessTypeDef.class);
+			when(accessTypeDef.getName()).thenReturn(access);
+			accessTypeDefs.add(accessTypeDef);
+		}
+		when(serviceDef.getAccessTypes()).thenReturn(accessTypeDefs);
+		return serviceDef;
+	}
+
+	List<RangerPolicyItemAccess> createItemAccess(Object[][] data) {
+		List<RangerPolicyItemAccess> accesses = new ArrayList<RangerPolicyItemAccess>();
+		for (Object[] row : data) {
+			RangerPolicyItemAccess access = mock(RangerPolicyItemAccess.class);
+			when(access.getType()).thenReturn((String)row[0]);
+			when(access.getIsAllowed()).thenReturn((Boolean)row[1]);
+			accesses.add(access);
+		}
+		return accesses;
+	}
+
+	List<RangerPolicyItem> createPolicyItems(Object[] data) {
+		List<RangerPolicyItem> policyItems = new ArrayList<RangerPolicyItem>();
+		for (Object object : data) {
+			@SuppressWarnings("unchecked")
+			Map<String, Object[]> map = (Map<String, Object[]>) object; 
+			RangerPolicyItem policyItem = mock(RangerPolicyItem.class);
+			
+			List<String> usersList = null;
+			if (map.containsKey("users")) {
+				usersList = Arrays.asList((String[])map.get("users"));
+			}
+			when(policyItem.getUsers()).thenReturn(usersList);
+			
+			List<String> groupsList = null;
+			if (map.containsKey("groups")) {
+				groupsList = Arrays.asList((String[])map.get("groups"));
+			}
+			when(policyItem.getGroups()).thenReturn(groupsList);
+			
+			String[] accesses = (String[])map.get("accesses");;
+			Boolean[] isAllowedFlags = (Boolean[])map.get("isAllowed");
+			List<RangerPolicyItemAccess> accessesList = null;
+			if (accesses != null && isAllowedFlags != null) {
+				accessesList = new ArrayList<RangerPolicyItemAccess>();
+				for (int i = 0; i < accesses.length; i++) {
+					String access = accesses[i];
+					Boolean isAllowed = isAllowedFlags[i]; 
+					RangerPolicyItemAccess itemAccess = mock(RangerPolicyItemAccess.class);
+					when(itemAccess.getType()).thenReturn(access);
+					when(itemAccess.getIsAllowed()).thenReturn(isAllowed);
+					accessesList.add(itemAccess);
+				}
+			}
+			when(policyItem.getAccesses()).thenReturn(accessesList);
+			
+			policyItems.add(policyItem);
+		}
+		return policyItems;
+	}
+
+	List<RangerResourceDef> createResourceDefs(Object[][] data) {
+		// if data itself is null then return null back
+		if (data == null) {
+			return null;
+		}
+		List<RangerResourceDef> defs = new ArrayList<RangerResourceDef>();
+		for (Object[] row : data) {
+			RangerResourceDef aDef = null;
+			if (row != null) {
+				String name = null;
+				Boolean mandatory = null;
+				String regExPattern = null;
+				Boolean isExcludesSupported = null;
+				Boolean isRecursiveSupported = null;
+				switch(row.length) {
+				case 5:
+					isRecursiveSupported = (Boolean)row[4];
+				case 4:
+					isExcludesSupported = (Boolean)row[3];
+				case 3:
+					regExPattern = (String)row[2];
+				case 2:
+					mandatory = (Boolean)row[1];
+				case 1:
+					name = (String)row[0];
+				}
+				aDef = mock(RangerResourceDef.class);
+				when(aDef.getName()).thenReturn(name);
+				when(aDef.getMandatory()).thenReturn(mandatory);
+				when(aDef.getValidationRegEx()).thenReturn(regExPattern);
+				when(aDef.getExcludesSupported()).thenReturn(isExcludesSupported);
+				when(aDef.getRecursiveSupported()).thenReturn(isRecursiveSupported);
+			}
+			defs.add(aDef);
+		}
+		return defs;
+	}
+
+	List<RangerResourceDef> createResourceDefs2(Object[][] data) {
+		// if data itself is null then return null back
+		if (data == null) {
+			return null;
+		}
+		List<RangerResourceDef> defs = new ArrayList<RangerResourceDef>();
+		for (Object[] row : data) {
+			RangerResourceDef aDef = null;
+			if (row != null) {
+				String name = null;
+				Boolean isExcludesSupported = null;
+				Boolean isRecursiveSupported = null;
+				switch(row.length) {
+				case 3:
+					isRecursiveSupported = (Boolean)row[2]; // note: falls through to next case
+				case 2:
+					isExcludesSupported = (Boolean)row[1]; // note: falls through to next case
+				case 1:
+					name = (String)row[0];
+				}
+				aDef = mock(RangerResourceDef.class);
+				when(aDef.getName()).thenReturn(name);
+				when(aDef.getExcludesSupported()).thenReturn(isExcludesSupported);
+				when(aDef.getRecursiveSupported()).thenReturn(isRecursiveSupported);
+			}
+			defs.add(aDef);
+		}
+		return defs;
+	}
+
+	List<RangerResourceDef> createResourceDefsWithRegEx(String[][] data) {
+		// if data itself is null then return null back
+		if (data == null) {
+			return null;
+		}
+		List<RangerResourceDef> defs = new ArrayList<RangerResourceDef>();
+		for (String[] row : data) {
+			RangerResourceDef aDef = null;
+			if (row != null) {
+				String name = row[0];
+				String regEx = row[1];
+				aDef = mock(RangerResourceDef.class);
+				when(aDef.getName()).thenReturn(name);
+				when(aDef.getValidationRegEx()).thenReturn(regEx);
+			}
+			defs.add(aDef);
+		}
+		return defs;
+	}
+
+	Map<String, RangerPolicyResource> createPolicyResourceMap2(Object[][] input) {
+		if (input == null) {
+			return null;
+		}
+		Map<String, RangerPolicyResource> result = new HashMap<String, RangerPolicyResource>(input.length);
+		for (Object[] row : input) {
+			String resourceName = (String)row[0];
+			Boolean isExcludes = (Boolean)row[1];
+			Boolean isRecursive = (Boolean)row[2];
+			RangerPolicyResource aResource = mock(RangerPolicyResource.class);
+			when(aResource.getIsExcludes()).thenReturn(isExcludes);
+			when(aResource.getIsRecursive()).thenReturn(isRecursive);
+			result.put(resourceName, aResource);
+		}
+		return result;
+	}
+
+	List<RangerEnumElementDef> createEnumElementDefs(String[] input) {
+		if (input == null) {
+			return null;
+		}
+		List<RangerEnumElementDef> output = new ArrayList<RangerEnumElementDef>();
+		for (String elementName : input) {
+			RangerEnumElementDef aDef = mock(RangerEnumElementDef.class);
+			when(aDef.getName()).thenReturn(elementName);
+			output.add(aDef);
+		}
+		return output;
+	}
+
+	List<RangerEnumDef> createEnumDefs(Map<String, String[]> input) {
+		if (input == null) {
+			return null;
+		}
+		List<RangerEnumDef> defs = new ArrayList<RangerEnumDef>();
+		for (Map.Entry<String, String[]> entry : input.entrySet()) {
+			RangerEnumDef enumDef = mock(RangerEnumDef.class);
+			String enumName = entry.getKey();
+			if ("null".equals(enumName)) { // special handling to process null hint in enum-name
+				enumName = null;
+			}
+			when(enumDef.getName()).thenReturn(enumName);
+			List<RangerEnumElementDef> elements = createEnumElementDefs(entry.getValue());
+			when(enumDef.getElements()).thenReturn(elements);
+			// by default set default index to last element
+			when(enumDef.getDefaultIndex()).thenReturn(elements.size() - 1);
+			defs.add(enumDef);
+		}
+		return defs;
+	}
+
+	Map<String, RangerPolicyResource> createPolicyResourceMap(Object[][] input) {
+		if (input == null) {
+			return null;
+		}
+		Map<String, RangerPolicyResource> result = new HashMap<String, RangerPolicyResource>(input.length);
+		for (Object[] row : input) {
+			String resourceName = (String)row[0];
+			String[] valuesArray = (String[])row[1];
+			Boolean isExcludes = (Boolean)row[2];
+			Boolean isRecursive = (Boolean)row[3];
+			RangerPolicyResource aResource = mock(RangerPolicyResource.class);
+			if (valuesArray == null) {
+				when(aResource.getValues()).thenReturn(null);
+			} else {
+				when(aResource.getValues()).thenReturn(Arrays.asList(valuesArray));
+			}
+			when(aResource.getIsExcludes()).thenReturn(isExcludes);
+			when(aResource.getIsRecursive()).thenReturn(isRecursive);
+			result.put(resourceName, aResource);
+		}
+		return result;
+	}
+}


[4/4] incubator-ranger git commit: RANGER-278 move validation classes under org.apache.ranger.plugin.model.validation

Posted by ma...@apache.org.
RANGER-278 move validation classes under org.apache.ranger.plugin.model.validation

Signed-off-by: Madhan Neethiraj <ma...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/incubator-ranger/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ranger/commit/7bb68687
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ranger/tree/7bb68687
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ranger/diff/7bb68687

Branch: refs/heads/master
Commit: 7bb686873805b8157644dbd3e9e27632ef8c5590
Parents: 9b35976
Author: Alok Lal <al...@hortonworks.com>
Authored: Sat Mar 14 08:09:54 2015 -0700
Committer: Madhan Neethiraj <ma...@apache.org>
Committed: Sat Mar 14 11:41:44 2015 -0700

----------------------------------------------------------------------
 .../model/validation/RangerPolicyValidator.java | 496 ++++++++++++++++++
 .../validation/RangerServiceDefValidator.java   | 365 +++++++++++++
 .../validation/RangerServiceValidator.java      | 207 ++++++++
 .../model/validation/RangerValidator.java       | 480 +++++++++++++++++
 .../validation/RangerValidatorFactory.java      |  36 ++
 .../validation/ValidationFailureDetails.java    |  91 ++++
 .../ValidationFailureDetailsBuilder.java        |  64 +++
 .../validation/TestRangerPolicyValidator.java   | 524 +++++++++++++++++++
 .../TestRangerServiceDefValidator.java          | 355 +++++++++++++
 .../validation/TestRangerServiceValidator.java  | 240 +++++++++
 .../model/validation/TestRangerValidator.java   | 476 +++++++++++++++++
 .../model/validation/ValidationTestUtils.java   | 371 +++++++++++++
 .../ranger/rest/RangerPolicyValidator.java      | 496 ------------------
 .../ranger/rest/RangerServiceDefValidator.java  | 365 -------------
 .../ranger/rest/RangerServiceValidator.java     | 207 --------
 .../org/apache/ranger/rest/RangerValidator.java | 480 -----------------
 .../ranger/rest/RangerValidatorFactory.java     |  36 --
 .../org/apache/ranger/rest/ServiceREST.java     |   6 +-
 .../ranger/rest/ValidationFailureDetails.java   |  91 ----
 .../rest/ValidationFailureDetailsBuilder.java   |  64 ---
 .../ranger/rest/TestRangerPolicyValidator.java  | 524 -------------------
 .../rest/TestRangerServiceDefValidator.java     | 355 -------------
 .../ranger/rest/TestRangerServiceValidator.java | 240 ---------
 .../apache/ranger/rest/TestRangerValidator.java | 476 -----------------
 .../rest/TestServiceRESTForValidation.java      |   6 +-
 .../apache/ranger/rest/ValidationTestUtils.java | 371 -------------
 26 files changed, 3715 insertions(+), 3707 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerPolicyValidator.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerPolicyValidator.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerPolicyValidator.java
new file mode 100644
index 0000000..f5d6bff
--- /dev/null
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerPolicyValidator.java
@@ -0,0 +1,496 @@
+package org.apache.ranger.plugin.model.validation;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ranger.plugin.model.RangerPolicy;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItem;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemAccess;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
+import org.apache.ranger.plugin.model.RangerService;
+import org.apache.ranger.plugin.model.RangerServiceDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
+import org.apache.ranger.plugin.store.ServiceStore;
+
+import com.google.common.collect.Sets;
+
+public class RangerPolicyValidator extends RangerValidator {
+
+	private static final Log LOG = LogFactory.getLog(RangerPolicyValidator.class);
+
+	public RangerPolicyValidator(ServiceStore store) {
+		super(store);
+	}
+
+	public void validate(RangerPolicy policy, Action action) throws Exception {
+		if(LOG.isDebugEnabled()) {
+			LOG.debug(String.format("==> RangerPolicyValidator.validate(%s, %s)", policy, action));
+		}
+
+		List<ValidationFailureDetails> failures = new ArrayList<ValidationFailureDetails>();
+		boolean valid = isValid(policy, action, failures);
+		String message = "";
+		try {
+			if (!valid) {
+				message = serializeFailures(failures);
+				throw new Exception(message);
+			}
+		} finally {
+			if(LOG.isDebugEnabled()) {
+				LOG.debug(String.format("<== RangerPolicyValidator.validate(%s, %s): %s, reason[%s]", policy, action, valid, message));
+			}
+		}
+	}
+
+	@Override
+	boolean isValid(Long id, Action action, List<ValidationFailureDetails> failures) {
+		if(LOG.isDebugEnabled()) {
+			LOG.debug(String.format("==> RangerPolicyValidator.isValid(%s, %s, %s)", id, action, failures));
+		}
+
+		boolean valid = true;
+		if (action != Action.DELETE) {
+			failures.add(new ValidationFailureDetailsBuilder()
+				.isAnInternalError()
+				.becauseOf("isValid(Long) is only supported for DELETE")
+				.build());
+			valid = false;
+		} else if (id == null) {
+			failures.add(new ValidationFailureDetailsBuilder()
+				.field("id")
+				.isMissing()
+				.build());
+			valid = false;
+		} else if (getPolicy(id) == null) {
+			failures.add(new ValidationFailureDetailsBuilder()
+				.field("id")
+				.isSemanticallyIncorrect()
+				.becauseOf("no policy found for id[" + id + "]")
+				.build());
+			valid = false;
+		}
+
+		if(LOG.isDebugEnabled()) {
+			LOG.debug(String.format("<== RangerPolicyValidator.isValid(%s, %s, %s): %s", id, action, failures, valid));
+		}
+		return valid;
+	}
+
+	boolean isValid(RangerPolicy policy, Action action, List<ValidationFailureDetails> failures) {
+		if(LOG.isDebugEnabled()) {
+			LOG.debug(String.format("==> RangerPolicyValidator.isValid(%s, %s, %s)", policy, action, failures));
+		}
+
+		if (!(action == Action.CREATE || action == Action.UPDATE)) {
+			throw new IllegalArgumentException("isValid(RangerPolicy, ...) is only supported for create/update");
+		}
+		boolean valid = true;
+		if (policy == null) {
+			String message = "policy object passed in was null";
+			LOG.debug(message);
+			failures.add(new ValidationFailureDetailsBuilder()
+				.field("policy")
+				.isMissing()
+				.becauseOf(message)
+				.build());
+			valid = false;
+		} else {
+			Long id = policy.getId();
+			if (action == Action.UPDATE) { // id is ignored for CREATE
+				if (id == null) {
+					String message = "policy id was null/empty/blank"; 
+					LOG.debug(message);
+					failures.add(new ValidationFailureDetailsBuilder()
+						.field("id")
+						.isMissing()
+						.becauseOf(message)
+						.build());
+					valid = false;
+				} else if (getPolicy(id) == null) {
+					failures.add(new ValidationFailureDetailsBuilder()
+						.field("id")
+						.isSemanticallyIncorrect()
+						.becauseOf("no policy exists with id[" + id +"]")
+						.build());
+					valid = false;
+				}
+			}
+			String policyName = policy.getName();
+			String serviceName = policy.getService();
+			if (StringUtils.isBlank(policyName)) {
+				String message = "policy name was null/empty/blank[" + policyName + "]"; 
+				LOG.debug(message);
+				failures.add(new ValidationFailureDetailsBuilder()
+					.field("name")
+					.isMissing()
+					.becauseOf(message)
+					.build());
+				valid = false;
+			} else {
+				List<RangerPolicy> policies = getPolicies(policyName, serviceName);
+				if (CollectionUtils.isNotEmpty(policies)) {
+					if (policies.size() > 1) {
+						failures.add(new ValidationFailureDetailsBuilder()
+							.isAnInternalError()
+							.becauseOf("multiple policies found with the name[" + policyName + "]")
+							.build());
+						valid = false;
+					} else if (action == Action.CREATE) { // size == 1
+						failures.add(new ValidationFailureDetailsBuilder()
+							.field("name")
+							.isSemanticallyIncorrect()
+							.becauseOf("policy already exists with name[" + policyName + "]; its id is[" + policies.iterator().next().getId() + "]")
+							.build());
+						valid = false;
+					} else if (policies.iterator().next().getId() != id) { // size == 1 && action == UPDATE
+						failures.add(new ValidationFailureDetailsBuilder()
+							.field("id/name")
+							.isSemanticallyIncorrect()
+							.becauseOf("id/name conflict: another policy already exists with name[" + policyName + "], its id is[" + policies.iterator().next().getId() + "]")
+							.build());
+						valid = false;
+					}
+				}
+			}
+			RangerService service = null;
+			if (StringUtils.isBlank(serviceName)) {
+				failures.add(new ValidationFailureDetailsBuilder()
+				.field("service")
+				.isMissing()
+				.becauseOf("service name was null/empty/blank")
+				.build());
+				valid = false;
+			} else {
+				service = getService(serviceName);
+				if (service == null) {
+					failures.add(new ValidationFailureDetailsBuilder()
+						.field("service")
+						.isMissing()
+						.becauseOf("service name was null/empty/blank")
+						.build());
+					valid = false;
+				}
+			}
+			List<RangerPolicyItem> policyItems = policy.getPolicyItems();
+			boolean isAuditEnabled = getIsAuditEnabled(policy);
+			RangerServiceDef serviceDef = null;
+			String serviceDefName = null;
+			if (CollectionUtils.isEmpty(policyItems) && !isAuditEnabled) {
+				failures.add(new ValidationFailureDetailsBuilder()
+					.field("policy items")
+					.isMissing()
+					.becauseOf("at least one policy item must be specified if audit isn't enabled")
+					.build());
+				valid = false;
+			} else if (service != null) {
+				serviceDefName = service.getType();
+				serviceDef = getServiceDef(serviceDefName);
+				if (serviceDef == null) {
+					failures.add(new ValidationFailureDetailsBuilder()
+						.field("policy service def")
+						.isAnInternalError()
+						.becauseOf("Service def of policies service does not exist")
+						.build());
+					valid = false;
+				} else {
+					valid = isValidPolicyItems(policyItems, failures, serviceDef) && valid;
+				}
+			}
+			if (serviceDef != null) {
+				Set<String> mandatoryResources = getMandatoryResourceNames(serviceDef);
+				Set<String> policyResources = getPolicyResources(policy);
+				Set<String> missingResources = Sets.difference(mandatoryResources, policyResources);
+				if (!missingResources.isEmpty()) {
+					failures.add(new ValidationFailureDetailsBuilder()
+						.field("resources")
+						.subField(missingResources.iterator().next()) // we return any one parameter!
+						.isMissing()
+						.becauseOf("required resources[" + missingResources + "] are missing")
+						.build());
+					valid = false;
+				}
+				Set<String> allResource = getAllResourceNames(serviceDef);
+				Set<String> unknownResources = Sets.difference(policyResources, allResource);
+				if (!unknownResources.isEmpty()) {
+					failures.add(new ValidationFailureDetailsBuilder()
+						.field("resources")
+						.subField(unknownResources.iterator().next()) // we return any one parameter!
+						.isSemanticallyIncorrect()
+						.becauseOf("resource[" + unknownResources + "] is not valid for service-def[" + serviceDefName + "]")
+						.build());
+					valid = false;
+				}
+				Map<String, RangerPolicyResource> resourceMap = policy.getResources();
+				valid = isValidResourceValues(resourceMap, failures, serviceDef) && valid;
+				valid = isValidResourceFlags(resourceMap, failures, serviceDef.getResources(), serviceDefName, policyName) && valid;
+			}
+		}
+		
+		if(LOG.isDebugEnabled()) {
+			LOG.debug(String.format("<== RangerPolicyValidator.isValid(%s, %s, %s): %s", policy, action, failures, valid));
+		}
+		return valid;
+	}
+	
+	boolean isValidResourceFlags(final Map<String, RangerPolicyResource> inputPolicyResources, final List<ValidationFailureDetails> failures,
+			final List<RangerResourceDef> resourceDefs, final String serviceDefName, final String policyName) {
+		if(LOG.isDebugEnabled()) {
+			LOG.debug(String.format("==> RangerPolicyValidator.isValidResourceFlags(%s, %s, %s, %s, %s)", inputPolicyResources, failures, resourceDefs, serviceDefName, policyName));
+		}
+
+		boolean valid = true;
+		if (inputPolicyResources == null) {
+			LOG.debug("isValidResourceFlags: resourceMap is null");
+		} else if (resourceDefs == null) {
+			LOG.debug("isValidResourceFlags: service Def is null");
+		} else {
+			Map<String, RangerPolicyResource> policyResources = getPolicyResourceWithLowerCaseKeys(inputPolicyResources);
+			for (RangerResourceDef resourceDef : resourceDefs) {
+				if (resourceDef == null) {
+					failures.add(new ValidationFailureDetailsBuilder()
+						.field("resource-def")
+						.isAnInternalError()
+						.becauseOf("a resource-def on resource def collection of service-def[" + serviceDefName + "] was null")
+						.build());
+					valid = false;
+				} else if (StringUtils.isBlank(resourceDef.getName())) {
+					failures.add(new ValidationFailureDetailsBuilder()
+						.field("resource-def-name")
+						.isAnInternalError()
+						.becauseOf("name of a resource-def on resource def collection of service-def[" + serviceDefName + "] was null")
+						.build());
+					valid = false;
+				} else {
+					String resourceName = resourceDef.getName().toLowerCase();
+					RangerPolicyResource policyResource = policyResources.get(resourceName);
+					if (policyResource == null) {
+						if (LOG.isDebugEnabled()) {
+							LOG.debug("a policy-resource object for resource[" + resourceName + "] on policy [" + policyName + "] was null");
+						}
+					} else {
+						boolean excludesSupported = Boolean.TRUE.equals(resourceDef.getExcludesSupported()); // could be null
+						boolean policyIsExcludes = Boolean.TRUE.equals(policyResource.getIsExcludes()); // could be null
+						if (policyIsExcludes && !excludesSupported) {
+							failures.add(new ValidationFailureDetailsBuilder()
+								.field("isExcludes")
+								.subField(resourceName)
+								.isSemanticallyIncorrect()
+								.becauseOf("isExcludes specified as [" + policyIsExcludes + "] for resource [" + resourceName + "] which doesn't support isExcludes")
+								.build());
+							valid = false;
+						}
+						boolean recursiveSupported = Boolean.TRUE.equals(resourceDef.getRecursiveSupported());
+						boolean policyIsRecursive = Boolean.TRUE.equals(policyResource.getIsRecursive());
+						if (policyIsRecursive && !recursiveSupported) {
+							failures.add(new ValidationFailureDetailsBuilder()
+								.field("isRecursive")
+								.subField(resourceName)
+								.isSemanticallyIncorrect()
+								.becauseOf("isRecursive specified as [" + policyIsRecursive + "] for resource [" + resourceName + "] which doesn't support isRecursive")
+								.build());
+							valid = false;
+						}
+					}
+				}
+			}
+		}
+
+		if(LOG.isDebugEnabled()) {
+			LOG.debug(String.format("<== RangerPolicyValidator.isValidResourceFlags(%s, %s, %s, %s, %s): %s", inputPolicyResources, failures, resourceDefs, serviceDefName, policyName, valid));
+		}
+		return valid;
+	}
+
+	boolean isValidResourceValues(Map<String, RangerPolicyResource> resourceMap, List<ValidationFailureDetails> failures, RangerServiceDef serviceDef) {
+		if(LOG.isDebugEnabled()) {
+			LOG.debug(String.format("==> RangerPolicyValidator.isValidResourceValues(%s, %s, %s)", resourceMap, failures, serviceDef));
+		}
+
+		boolean valid = true;
+		if (resourceMap == null) {
+			LOG.debug("isValidResourceValues: resourceMap is null");
+		} else if (serviceDef == null) {
+			LOG.debug("isValidResourceValues: service Def is null");
+		} else {
+			Map<String, String> validationRegExMap = getValidationRegExes(serviceDef);
+			for (Map.Entry<String, RangerPolicyResource> entry : resourceMap.entrySet()) {
+				String name = entry.getKey();
+				RangerPolicyResource policyResource = entry.getValue();
+				if (validationRegExMap.containsKey(name) && policyResource != null && CollectionUtils.isNotEmpty(policyResource.getValues())) {
+					String regEx = validationRegExMap.get(name);
+					for (String aValue : policyResource.getValues()) {
+						if (StringUtils.isBlank(aValue)) {
+							LOG.debug("resource value was blank");
+						} else if (!aValue.matches(regEx)) {
+							failures.add(new ValidationFailureDetailsBuilder()
+								.field("resource-values")
+								.subField(name)
+								.isSemanticallyIncorrect()
+								.becauseOf("resources value[" + aValue + "] does not match validation regex[" + regEx + "] defined on service-def[" + serviceDef.getName() + "]")
+								.build());
+							valid = false;
+						}
+					}
+				}
+			}
+		}
+
+		if(LOG.isDebugEnabled()) {
+			LOG.debug(String.format("<== RangerPolicyValidator.isValidResourceValues(%s, %s, %s): %s", resourceMap, failures, serviceDef, valid));
+		}
+		return valid;
+	}
+
+	boolean isValidPolicyItems(List<RangerPolicyItem> policyItems, List<ValidationFailureDetails> failures, RangerServiceDef serviceDef) {
+		if(LOG.isDebugEnabled()) {
+			LOG.debug(String.format("==> RangerPolicyValidator.isValid(%s, %s, %s)", policyItems, failures, serviceDef));
+		}
+
+		boolean valid = true;
+		if (CollectionUtils.isEmpty(policyItems)) {
+			LOG.debug("policy items collection was null/empty");
+		} else {
+			for (RangerPolicyItem policyItem : policyItems) {
+				if (policyItem == null) {
+					failures.add(new ValidationFailureDetailsBuilder()
+						.field("policy item")
+						.isMissing()
+						.becauseOf("policy items object was null")
+						.build());
+					valid = false;
+				} else {
+					// we want to go through all elements even though one may be bad so all failures are captured
+					valid = isValidPolicyItem(policyItem, failures, serviceDef) && valid;
+				}
+			}
+		}
+
+		if(LOG.isDebugEnabled()) {
+			LOG.debug(String.format("<== RangerPolicyValidator.isValid(%s, %s, %s): %s", policyItems, failures, serviceDef, valid));
+		}
+		return valid;
+	}
+
+	boolean isValidPolicyItem(RangerPolicyItem policyItem, List<ValidationFailureDetails> failures, RangerServiceDef serviceDef) {
+		if(LOG.isDebugEnabled()) {
+			LOG.debug(String.format("==> RangerPolicyValidator.isValid(%s, %s, %s)", policyItem, failures, serviceDef));
+		}
+		
+		boolean valid = true;
+		if (policyItem == null) {
+			LOG.debug("policy item was null!");
+		} else {
+			// access items collection can't be empty and should be otherwise valid
+			if (CollectionUtils.isEmpty(policyItem.getAccesses())) {
+				failures.add(new ValidationFailureDetailsBuilder()
+					.field("policy item accesses")
+					.isMissing()
+					.becauseOf("policy items accesses collection was null")
+					.build());
+				valid = false;
+			} else {
+				valid = isValidItemAccesses(policyItem.getAccesses(), failures, serviceDef) && valid;
+			}
+			// both users and user-groups collections can't be empty
+			if (CollectionUtils.isEmpty(policyItem.getUsers()) && CollectionUtils.isEmpty(policyItem.getGroups())) {
+				failures.add(new ValidationFailureDetailsBuilder()
+					.field("policy item users/user-groups")
+					.isMissing()
+					.becauseOf("both users and user-groups collections on the policy item were null/empty")
+					.build());
+				valid = false;
+			}
+		}
+
+		if(LOG.isDebugEnabled()) {
+			LOG.debug(String.format("<== RangerPolicyValidator.isValid(%s, %s, %s): %s", policyItem, failures, serviceDef, valid));
+		}
+		return valid;
+	}
+
+	boolean isValidItemAccesses(List<RangerPolicyItemAccess> accesses, List<ValidationFailureDetails> failures, RangerServiceDef serviceDef) {
+		if(LOG.isDebugEnabled()) {
+			LOG.debug(String.format("==> RangerPolicyValidator.isValid(%s, %s, %s)", accesses, failures, serviceDef));
+		}
+		
+		boolean valid = true;
+		if (CollectionUtils.isEmpty(accesses)) {
+			LOG.debug("policy item accesses collection was null/empty!");
+		} else {
+			Set<String> accessTypes = getAccessTypes(serviceDef);
+			for (RangerPolicyItemAccess access : accesses) {
+				if (access == null) {
+					failures.add(new ValidationFailureDetailsBuilder()
+						.field("policy item access")
+						.isMissing()
+						.becauseOf("policy items access object was null")
+						.build());
+					valid = false;
+				} else {
+					// we want to go through all elements even though one may be bad so all failures are captured
+					valid = isValidPolicyItemAccess(access, failures, accessTypes) && valid;
+				}
+			}
+		}
+
+		if(LOG.isDebugEnabled()) {
+			LOG.debug(String.format("<== RangerPolicyValidator.isValid(%s, %s): %s", accesses, failures, serviceDef, valid));
+		}
+		return valid;
+	}
+
+	boolean isValidPolicyItemAccess(RangerPolicyItemAccess access, List<ValidationFailureDetails> failures, Set<String> accessTypes) {
+		if(LOG.isDebugEnabled()) {
+			LOG.debug(String.format("==> RangerPolicyValidator.isValidPolicyItemAccess(%s, %s, %s)", access, failures, accessTypes));
+		}
+		
+		boolean valid = true;
+		if (CollectionUtils.isEmpty(accessTypes)) { // caller should firewall this argument!
+			LOG.debug("isValidPolicyItemAccess: accessTypes was null!");
+		} else if (access == null) {
+			LOG.debug("isValidPolicyItemAccess: policy item access was null!");
+		} else {
+			String accessType = access.getType();
+			if (StringUtils.isBlank(accessType)) {
+				failures.add(new ValidationFailureDetailsBuilder()
+					.field("policy item access type")
+					.isMissing()
+					.becauseOf("policy items access type's name was null/empty/blank")
+					.build());
+				valid = false;
+			} else if (!accessTypes.contains(accessType.toLowerCase())) {
+				String message = String.format("access type[%s] not among valid types for service[%s]", accessType, accessTypes);
+				LOG.debug(message);
+				failures.add(new ValidationFailureDetailsBuilder()
+					.field("policy item access type")
+					.isSemanticallyIncorrect()
+					.becauseOf(message)
+					.build());
+				valid = false;
+			}
+			Boolean isAllowed = access.getIsAllowed();
+			// it can be null (which is treated as allowed) but not false
+			if (isAllowed != null && isAllowed == false) {
+				String message = "access type is set to deny.  Currently deny access types are not supported.";
+				LOG.debug(message);
+				failures.add(new ValidationFailureDetailsBuilder()
+					.field("policy item access type allowed")
+					.isSemanticallyIncorrect()
+					.becauseOf(message)
+					.build());
+				valid = false;
+			}
+		}
+		
+		if(LOG.isDebugEnabled()) {
+			LOG.debug(String.format("<== RangerPolicyValidator.isValidPolicyItemAccess(%s, %s, %s): %s", access, failures, accessTypes, valid));
+		}
+		return valid;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceDefValidator.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceDefValidator.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceDefValidator.java
new file mode 100644
index 0000000..a870e28
--- /dev/null
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceDefValidator.java
@@ -0,0 +1,365 @@
+package org.apache.ranger.plugin.model.validation;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ranger.plugin.model.RangerServiceDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumElementDef;
+import org.apache.ranger.plugin.store.ServiceStore;
+
+import com.google.common.collect.Sets;
+
+public class RangerServiceDefValidator extends RangerValidator {
+
+	private static final Log LOG = LogFactory.getLog(RangerServiceDefValidator.class);
+
+	public RangerServiceDefValidator(ServiceStore store) {
+		super(store);
+	}
+
+	public void validate(final RangerServiceDef serviceDef, final Action action) throws Exception {
+		if(LOG.isDebugEnabled()) {
+			LOG.debug(String.format("==> RangerServiceDefValidator.validate(%s, %s)", serviceDef, action));
+		}
+
+		List<ValidationFailureDetails> failures = new ArrayList<ValidationFailureDetails>();
+		boolean valid = isValid(serviceDef, action, failures);
+		String message = "";
+		try {
+			if (!valid) {
+				message = serializeFailures(failures);
+				throw new Exception(message);
+			}
+		} finally {
+			if(LOG.isDebugEnabled()) {
+				LOG.debug(String.format("<== RangerServiceDefValidator.validate(%s, %s): %s, reason[%s]", serviceDef, action, valid, message));
+			}
+		}
+	}
+
+	boolean isValid(final Long id, final Action action, final List<ValidationFailureDetails> failures) {
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("==> RangerServiceDefValidator.isValid(" + id + ")");
+		}
+
+		boolean valid = true;
+		if (action != Action.DELETE) {
+			failures.add(new ValidationFailureDetailsBuilder()
+				.isAnInternalError()
+				.becauseOf("unsupported action[" + action + "]; isValid(Long) is only supported for DELETE")
+				.build());
+			valid = false;
+		} else if (id == null) {
+			failures.add(new ValidationFailureDetailsBuilder()
+				.field("id")
+				.isMissing()
+				.build());
+			valid = false;
+		} else if (getServiceDef(id) == null) {
+			failures.add(new ValidationFailureDetailsBuilder()
+				.field("id")
+				.isSemanticallyIncorrect()
+				.becauseOf("no service def found for id[" + id + "]")
+				.build());
+			valid = false;
+		}
+
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("<== RangerServiceDefValidator.isValid(" + id + "): " + valid);
+		}
+		return valid;
+	}
+	
+	boolean isValid(final RangerServiceDef serviceDef, final Action action, final List<ValidationFailureDetails> failures) {
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("==> RangerServiceDefValidator.isValid(" + serviceDef + ")");
+		}
+		
+		if (!(action == Action.CREATE || action == Action.UPDATE)) {
+			throw new IllegalArgumentException("isValid(RangerServiceDef, ...) is only supported for CREATE/UPDATE");
+		}
+		boolean valid = true;
+		if (serviceDef == null) {
+			String message = "service def object passed in was null";
+			LOG.debug(message);
+			failures.add(new ValidationFailureDetailsBuilder()
+				.field("service def")
+				.isMissing()
+				.becauseOf(message)
+				.build());
+			valid = false;
+		} else {
+			Long id = serviceDef.getId();
+			if (action == Action.UPDATE) { // id is ignored for CREATE
+				if (id == null) {
+					String message = "service def id was null/empty/blank"; 
+					LOG.debug(message);
+					failures.add(new ValidationFailureDetailsBuilder()
+						.field("id")
+						.isMissing()
+						.becauseOf(message)
+						.build());
+					valid = false;
+				} else if (getServiceDef(id) == null) {
+					failures.add(new ValidationFailureDetailsBuilder()
+						.field("id")
+						.isSemanticallyIncorrect()
+						.becauseOf("no service def exists with id[" + id +"]")
+						.build());
+					valid = false;
+				}
+			}
+			// validate the service def name
+			String name = serviceDef.getName();
+			boolean nameSpecified = StringUtils.isNotBlank(name);
+			if (!nameSpecified) {
+				String message = "service def name[" + name + "] was null/empty/blank"; 
+				LOG.debug(message);
+				failures.add(new ValidationFailureDetailsBuilder()
+					.field("name")
+					.isMissing()
+					.becauseOf(message)
+					.build());
+				valid = false;
+			} else {
+				RangerServiceDef otherServiceDef = getServiceDef(name);
+				if (otherServiceDef != null && action == Action.CREATE) {
+					failures.add(new ValidationFailureDetailsBuilder()
+						.field("name")
+						.isSemanticallyIncorrect()
+						.becauseOf("service def with the name[" + name + "] already exists")
+						.build());
+					valid = false;
+				} else if (otherServiceDef != null && otherServiceDef.getId() !=null && otherServiceDef.getId() != id) {
+					failures.add(new ValidationFailureDetailsBuilder()
+						.field("id/name")
+						.isSemanticallyIncorrect()
+						.becauseOf("id/name conflict: another service def already exists with name[" + name + "], its id is [" + otherServiceDef.getId() + "]")
+						.build());
+					valid = false;
+				}
+			}
+			if (CollectionUtils.isEmpty(serviceDef.getAccessTypes())) {
+				failures.add(new ValidationFailureDetailsBuilder()
+					.field("access types")
+					.isMissing()
+					.becauseOf("access types collection was null/empty")
+					.build());
+				valid = false;
+			} else {
+				valid = isValidAccessTypes(serviceDef.getAccessTypes(), failures) && valid;
+			}
+			if (CollectionUtils.isEmpty(serviceDef.getEnums())) {
+				LOG.debug("No enums specified on the service def.  Ok!");
+			} else {
+				valid = isValidEnums(serviceDef.getEnums(), failures) && valid;
+			}
+		}
+		
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("<== RangerServiceDefValidator.isValid(" + serviceDef + "): " + valid);
+		}
+		return valid;
+	}
+
+	boolean isValidAccessTypes(final List<RangerAccessTypeDef> accessTypeDefs, final List<ValidationFailureDetails> failures) {
+		if(LOG.isDebugEnabled()) {
+			LOG.debug(String.format("==> RangerServiceDefValidator.isValidAccessTypes(%s, %s)", accessTypeDefs, failures));
+		}
+		
+		boolean valid = true;
+		if (CollectionUtils.isEmpty(accessTypeDefs)) {
+			LOG.debug("access type def collection is empty/null");
+		} else {
+			List<RangerAccessTypeDef> defsWithImpliedGrants = new ArrayList<RangerAccessTypeDef>();
+			Set<String> accessNames = new HashSet<String>();
+			for (RangerAccessTypeDef def : accessTypeDefs) {
+				String name = def.getName();
+				// name can't be null/empty/blank
+				if (StringUtils.isBlank(name)) {
+					failures.add(new ValidationFailureDetailsBuilder()
+						.field("access type name")
+						.isMissing()
+						.becauseOf("access type name[" + name + "] is null/empty")
+						.build());
+					valid = false;
+				} else if (accessNames.contains(name.toLowerCase())) {
+					failures.add(new ValidationFailureDetailsBuilder()
+						.field("access type name")
+						.subField(name)
+						.isSemanticallyIncorrect()
+						.becauseOf("duplicate access type names in access types collection: [" + name + "]")
+						.build());
+					valid = false;
+				} else {
+					accessNames.add(name.toLowerCase()); // we have a new unique access type
+				}
+				if (CollectionUtils.isNotEmpty(def.getImpliedGrants())) {
+					defsWithImpliedGrants.add(def);
+				}
+			}
+			// validate implied grants
+			for (RangerAccessTypeDef def : defsWithImpliedGrants) {
+				Collection<String> impliedGrants = getImpliedGrants(def);
+				Set<String> unknownAccessTypes = Sets.difference(Sets.newHashSet(impliedGrants), accessNames);
+				if (!unknownAccessTypes.isEmpty()) {
+					failures.add(new ValidationFailureDetailsBuilder()
+						.field("implied grants")
+						.subField(unknownAccessTypes.iterator().next())  // we return just on item here.  Message has all unknow items
+						.isSemanticallyIncorrect()
+						.becauseOf("implied grant[" + impliedGrants + "] contains an unknown access types[" + unknownAccessTypes + "]")
+						.build());
+					valid = false;
+				}
+				// implied grant should not imply itself! 
+				String name = def.getName(); // note: this name could be null/blank/empty!
+				if (impliedGrants.contains(name)) {
+					failures.add(new ValidationFailureDetailsBuilder()
+						.field("implied grants")
+						.subField(name)
+						.isSemanticallyIncorrect()
+						.becauseOf("implied grants list [" + impliedGrants + "] for access type[" + name + "] contains itself")
+						.build());
+					valid = false;
+				}
+			}
+		}
+		
+		if(LOG.isDebugEnabled()) {
+			LOG.debug(String.format("<== RangerServiceDefValidator.isValidAccessTypes(%s, %s): %s", accessTypeDefs, failures, valid));
+		}
+		return valid;
+	}
+
+	boolean isValidEnums(List<RangerEnumDef> enumDefs, List<ValidationFailureDetails> failures) {
+		if(LOG.isDebugEnabled()) {
+			LOG.debug(String.format("==> RangerServiceDefValidator.isValidEnums(%s, %s)", enumDefs, failures));
+		}
+		
+		boolean valid = true;
+		if (CollectionUtils.isEmpty(enumDefs)) {
+			LOG.debug("enum def collection passed in was null/empty");
+		} else {
+			Set<String> enumNames = new HashSet<String>();
+			for (RangerEnumDef enumDef : enumDefs) {
+				if (enumDef == null) {
+					failures.add(new ValidationFailureDetailsBuilder()
+						.field("enum def")
+						.isMissing()
+						.becauseOf("An enum def in enums collection is null")
+						.build());
+					valid = false;
+				} else {
+					// enum-names must non-blank and be unique to a service definition
+					String enumName = enumDef.getName();
+					if (StringUtils.isBlank(enumName)) {
+						failures.add(new ValidationFailureDetailsBuilder()
+							.field("enum def name")
+							.isMissing()
+							.becauseOf("enum name [" + enumName + "] is null/empty")
+							.build());
+						valid = false;
+					} else if (enumNames.contains(enumName.toLowerCase())) {
+						failures.add(new ValidationFailureDetailsBuilder()
+							.field("enum def name")
+							.subField(enumName)
+							.isSemanticallyIncorrect()
+							.becauseOf("dumplicate enum name [" + enumName + "] found")
+							.build());
+						valid = false;
+					} else {
+						enumNames.add(enumName.toLowerCase());
+					}
+					// enum must contain at least one valid value and those values should be non-blank and distinct
+					if (CollectionUtils.isEmpty(enumDef.getElements())) {
+						failures.add(new ValidationFailureDetailsBuilder()
+							.field("enum values")
+							.subField(enumName)
+							.isMissing()
+							.becauseOf("enum [" + enumName + "] does not have any elements")
+							.build());
+						valid = false;
+					} else {
+						valid = isValidEnumElements(enumDef.getElements(), failures, enumName) && valid;
+						// default index should be valid
+						int defaultIndex = getEnumDefaultIndex(enumDef);
+						if (defaultIndex < 0 || defaultIndex >= enumDef.getElements().size()) { // max index is one less than the size of the elements list
+							failures.add(new ValidationFailureDetailsBuilder()
+								.field("enum default index")
+								.subField(enumName)
+								.isSemanticallyIncorrect()
+								.becauseOf("default index[" + defaultIndex + "] for enum [" + enumName + "] is invalid")
+								.build());
+							valid = false;
+						}
+					}
+				}
+			}
+		}
+		
+		if(LOG.isDebugEnabled()) {
+			LOG.debug(String.format("<== RangerServiceDefValidator.isValidEnums(%s, %s): %s", enumDefs, failures, valid));
+		}
+		return valid;
+	}
+
+	boolean isValidEnumElements(List<RangerEnumElementDef> enumElementsDefs, List<ValidationFailureDetails> failures, String enumName) {
+		if(LOG.isDebugEnabled()) {
+			LOG.debug(String.format("==> RangerServiceDefValidator.isValidEnums(%s, %s)", enumElementsDefs, failures));
+		}
+		
+		boolean valid = true;
+		if (CollectionUtils.isEmpty(enumElementsDefs)) {
+			LOG.debug("Enum elements list passed in was null/empty!");
+		} else {
+			// enum element names should be valid and distinct
+			Set<String> elementNames = new HashSet<String>();
+			for (RangerEnumElementDef elementDef : enumElementsDefs) {
+				if (elementDef == null) {
+					failures.add(new ValidationFailureDetailsBuilder()
+						.field("enum element")
+						.subField(enumName)
+						.isMissing()
+						.becauseOf("An enum element in enum element collection of enum [" + enumName + "] is null")
+						.build());
+					valid = false;
+				} else {
+					String elementName = elementDef.getName();
+					if (StringUtils.isBlank(elementName)) {
+						failures.add(new ValidationFailureDetailsBuilder()
+							.field("enum element name")
+							.subField(enumName)
+							.isMissing()
+							.becauseOf("Name of an element of enum [" + enumName + "] is null/empty[" + elementName + "]")
+							.build());
+						valid = false;
+					} else if (elementNames.contains(elementName.toLowerCase())) {
+						failures.add(new ValidationFailureDetailsBuilder()
+							.field("enum element name")
+							.subField(enumName)
+							.isSemanticallyIncorrect()
+							.becauseOf("dumplicate enum element name [" + elementName + "] found for enum[" + enumName + "]")
+							.build());
+						valid = false;
+					} else {
+						elementNames.add(elementName.toLowerCase());
+					}
+				}
+			}
+		}
+		
+		if(LOG.isDebugEnabled()) {
+			LOG.debug(String.format("<== RangerServiceDefValidator.isValidEnums(%s, %s): %s", enumElementsDefs, failures, valid));
+		}
+		return valid;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceValidator.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceValidator.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceValidator.java
new file mode 100644
index 0000000..2019284
--- /dev/null
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceValidator.java
@@ -0,0 +1,207 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF 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.apache.ranger.plugin.model.validation;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ranger.plugin.model.RangerService;
+import org.apache.ranger.plugin.model.RangerServiceDef;
+import org.apache.ranger.plugin.store.ServiceStore;
+
+import com.google.common.collect.Sets;
+
+public class RangerServiceValidator extends RangerValidator {
+
+	private static final Log LOG = LogFactory.getLog(RangerServiceValidator.class);
+
+	public RangerServiceValidator(ServiceStore store) {
+		super(store);
+	}
+
+	public void validate(RangerService service, Action action) throws Exception {
+		if(LOG.isDebugEnabled()) {
+			LOG.debug(String.format("==> RangerServiceValidator.validate(%s, %s)", service, action));
+		}
+
+		List<ValidationFailureDetails> failures = new ArrayList<ValidationFailureDetails>();
+		boolean valid = isValid(service, action, failures);
+		String message = "";
+		try {
+			if (!valid) {
+				message = serializeFailures(failures);
+				throw new Exception(message);
+			}
+		} finally {
+			if(LOG.isDebugEnabled()) {
+				LOG.debug(String.format("<== RangerServiceValidator.validate(%s, %s): %s, reason[%s]", service, action, valid, message));
+			}
+		}
+	}
+	
+	boolean isValid(Long id, Action action, List<ValidationFailureDetails> failures) {
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("==> RangerServiceValidator.isValid(" + id + ")");
+		}
+
+		boolean valid = true;
+		if (action != Action.DELETE) {
+			failures.add(new ValidationFailureDetailsBuilder()
+				.isAnInternalError()
+				.becauseOf("unsupported action[" + action + "]; isValid(Long) is only supported for DELETE")
+				.build());
+			valid = false;
+		} else if (id == null) {
+			failures.add(new ValidationFailureDetailsBuilder()
+				.field("id")
+				.isMissing()
+				.build());
+			valid = false;
+		} else if (getService(id) == null) {
+			failures.add(new ValidationFailureDetailsBuilder()
+				.field("id")
+				.isSemanticallyIncorrect()
+				.becauseOf("no service found for id[" + id + "]")
+				.build());
+			valid = false;
+		}
+
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("<== RangerServiceValidator.isValid(" + id + "): " + valid);
+		}
+		return valid;
+	}
+	
+	boolean isValid(RangerService service, Action action, List<ValidationFailureDetails> failures) {
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("==> RangerServiceValidator.isValid(" + service + ")");
+		}
+		if (!(action == Action.CREATE || action == Action.UPDATE)) {
+			throw new IllegalArgumentException("isValid(RangerService, ...) is only supported for CREATE/UPDATE");
+		}
+		
+		boolean valid = true;
+		if (service == null) {
+			String message = "service object passed in was null";
+			LOG.debug(message);
+			failures.add(new ValidationFailureDetailsBuilder()
+				.field("service")
+				.isMissing()
+				.becauseOf(message)
+				.build());
+			valid = false;
+		} else {
+			Long id = service.getId();
+			if (action == Action.UPDATE) { // id is ignored for CREATE
+				if (id == null) {
+					String message = "service id was null/empty/blank"; 
+					LOG.debug(message);
+					failures.add(new ValidationFailureDetailsBuilder()
+						.field("id")
+						.isMissing()
+						.becauseOf(message)
+						.build());
+					valid = false;
+				} else if (getService(id) == null) {
+					failures.add(new ValidationFailureDetailsBuilder()
+						.field("id")
+						.isSemanticallyIncorrect()
+						.becauseOf("no service exists with id[" + id +"]")
+						.build());
+					valid = false;
+				}
+			}
+			String name = service.getName();
+			boolean nameSpecified = StringUtils.isNotBlank(name);
+			RangerServiceDef serviceDef = null;
+			if (!nameSpecified) {
+				String message = "service name[" + name + "] was null/empty/blank"; 
+				LOG.debug(message);
+				failures.add(new ValidationFailureDetailsBuilder()
+					.field("name")
+					.isMissing()
+					.becauseOf(message)
+					.build());
+				valid = false;
+			} else {
+				RangerService otherService = getService(name);
+				if (otherService != null && action == Action.CREATE) {
+					failures.add(new ValidationFailureDetailsBuilder()
+						.field("name")
+						.isSemanticallyIncorrect()
+						.becauseOf("service with the name[" + name + "] already exists")
+						.build());
+					valid = false;
+				} else if (otherService != null && otherService.getId() !=null && otherService.getId() != id) {
+					failures.add(new ValidationFailureDetailsBuilder()
+						.field("id/name")
+						.isSemanticallyIncorrect()
+						.becauseOf("id/name conflict: another service already exists with name[" + name + "], its id is [" + otherService.getId() + "]")
+						.build());
+					valid = false;
+				}
+			}
+			String type = service.getType();
+			boolean typeSpecified = StringUtils.isNotBlank(type);
+			if (!typeSpecified) {
+				failures.add(new ValidationFailureDetailsBuilder()
+					.field("type")
+					.isMissing()
+					.becauseOf("service def [" + type + "] was null/empty/blank")
+					.build());
+				valid = false;
+			} else {
+				serviceDef = getServiceDef(type);
+				if (serviceDef == null) {
+					failures.add(new ValidationFailureDetailsBuilder()
+						.field("type")
+						.isSemanticallyIncorrect()
+						.becauseOf("service def named[" + type + "] not found")
+						.build());
+					valid = false;
+				}
+			}
+			if (nameSpecified && serviceDef != null) {
+				// check if required parameters were specified
+				Set<String> reqiredParameters = getRequiredParameters(serviceDef);
+				Set<String> inputParameters = getServiceConfigParameters(service);
+				Set<String> missingParameters = Sets.difference(reqiredParameters, inputParameters);
+				if (!missingParameters.isEmpty()) {
+					failures.add(new ValidationFailureDetailsBuilder()
+						.field("configuration")
+						.subField(missingParameters.iterator().next()) // we return any one parameter!
+						.isMissing()
+						.becauseOf("required configuration parameter is missing; missing parameters: " + missingParameters)
+						.build());
+					valid = false;
+				}
+			}
+		}
+		
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("<== RangerServiceValidator.isValid(" + service + "): " + valid);
+		}
+		return valid;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerValidator.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerValidator.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerValidator.java
new file mode 100644
index 0000000..7bf744e
--- /dev/null
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerValidator.java
@@ -0,0 +1,480 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF 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.apache.ranger.plugin.model.validation;
+
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ranger.plugin.model.RangerPolicy;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
+import org.apache.ranger.plugin.model.RangerService;
+import org.apache.ranger.plugin.model.RangerServiceDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerServiceConfigDef;
+import org.apache.ranger.plugin.store.ServiceStore;
+import org.apache.ranger.plugin.util.SearchFilter;
+
+public abstract class RangerValidator {
+	
+	private static final Log LOG = LogFactory.getLog(RangerValidator.class);
+
+	ServiceStore _store;
+
+	public enum Action {
+		CREATE, UPDATE, DELETE;
+	};
+	
+	protected RangerValidator(ServiceStore store) {
+		if (store == null) {
+			throw new IllegalArgumentException("ServiceValidator(): store is null!");
+		}
+		_store = store;
+	}
+
+	public void validate(Long id, Action action) throws Exception {
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("==> RangerValidator.validate(" + id + ")");
+		}
+
+		List<ValidationFailureDetails> failures = new ArrayList<ValidationFailureDetails>();
+		if (isValid(id, action, failures)) {
+			if(LOG.isDebugEnabled()) {
+				LOG.debug("<== RangerValidator.validate(" + id + "): valid");
+			}
+		} else {
+			String message = serializeFailures(failures);
+			LOG.debug("<== RangerValidator.validate(" + id + "): invalid, reason[" + message + "]");
+			throw new Exception(message);
+		}
+	}
+	
+	/**
+	 * This method is expected to be overridden by sub-classes.  Default implementation provided to not burden implementers from having to implement methods that they know would never be called. 
+	 * @param id
+	 * @param action
+	 * @param failures
+	 * @return
+	 */
+	boolean isValid(Long id, Action action, List<ValidationFailureDetails> failures) {
+		failures.add(new ValidationFailureDetailsBuilder()
+				.isAnInternalError()
+				.becauseOf("unimplemented method called")
+				.build());
+		return false;
+	}
+
+	String serializeFailures(List<ValidationFailureDetails> failures) {
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("==> RangerValidator.getFailureMessage()");
+		}
+
+		String message = null;
+		if (CollectionUtils.isEmpty(failures)) {
+			LOG.warn("serializeFailures: called while list of failures is null/empty!");
+		} else {
+			StringBuilder builder = new StringBuilder();
+			for (ValidationFailureDetails aFailure : failures) {
+				builder.append(aFailure.toString());
+				builder.append(";");
+			}
+			message = builder.toString();
+		}
+
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("<== RangerValidator.serializeFailures(): " + message);
+		}
+		return message;
+	}
+
+	Set<String> getServiceConfigParameters(RangerService service) {
+		if (service == null || service.getConfigs() == null) {
+			return new HashSet<String>();
+		} else {
+			return service.getConfigs().keySet();
+		}
+	}
+
+	Set<String> getRequiredParameters(RangerServiceDef serviceDef) {
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("==> RangerValidator.getRequiredParameters(" + serviceDef + ")");
+		}
+
+		Set<String> result;
+		if (serviceDef == null) {
+			result = Collections.emptySet();
+		} else {
+			List<RangerServiceConfigDef> configs = serviceDef.getConfigs();
+			if (CollectionUtils.isEmpty(configs)) {
+				result = Collections.emptySet();
+			} else {
+				result = new HashSet<String>(configs.size()); // at worse all of the config items are required!
+				for (RangerServiceConfigDef configDef : configs) {
+					if (configDef.getMandatory()) {
+						result.add(configDef.getName());
+					}
+				}
+			}
+		}
+
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("<== RangerValidator.getRequiredParameters(" + serviceDef + "): " + result);
+		}
+		return result;
+	}
+
+	RangerServiceDef getServiceDef(Long id) {
+
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("==> RangerValidator.getServiceDef(" + id + ")");
+		}
+		RangerServiceDef result = null;
+		try {
+			result = _store.getServiceDef(id);
+		} catch (Exception e) {
+			LOG.debug("Encountred exception while retrieving service def from service store!", e);
+		}
+		
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("<== RangerValidator.getServiceDef(" + id + "): " + result);
+		}
+		return result;
+	}
+
+	RangerServiceDef getServiceDef(String type) {
+		
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("==> RangerValidator.getServiceDef(" + type + ")");
+		}
+		RangerServiceDef result = null;
+		try {
+			result = _store.getServiceDefByName(type);
+		} catch (Exception e) {
+			LOG.debug("Encountred exception while retrieving service definition from service store!", e);
+		}
+		
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("<== RangerValidator.getServiceDef(" + type + "): " + result);
+		}
+		return result;
+	}
+
+	RangerService getService(Long id) {
+		
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("==> RangerValidator.getService(" + id + ")");
+		}
+		RangerService result = null;
+		try {
+			result = _store.getService(id);
+		} catch (Exception e) {
+			LOG.debug("Encountred exception while retrieving service from service store!", e);
+		}
+		
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("<== RangerValidator.getService(" + id + "): " + result);
+		}
+		return result;
+	}
+
+	RangerService getService(String name) {
+		
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("==> RangerValidator.getService(" + name + ")");
+		}
+		RangerService result = null;
+		try {
+			result = _store.getServiceByName(name);
+		} catch (Exception e) {
+			LOG.debug("Encountred exception while retrieving service from service store!", e);
+		}
+		
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("<== RangerValidator.getService(" + name + "): " + result);
+		}
+		return result;
+	}
+
+	RangerPolicy getPolicy(Long id) {
+		
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("==> RangerValidator.getPolicy(" + id + ")");
+		}
+		RangerPolicy result = null;
+		try {
+			result = _store.getPolicy(id);
+		} catch (Exception e) {
+			LOG.debug("Encountred exception while retrieving policy from service store!", e);
+		}
+		
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("<== RangerValidator.getPolicy(" + id + "): " + result);
+		}
+		return result;
+	}
+
+	List<RangerPolicy> getPolicies(final String policyName, final String serviceName) {
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("==> RangerValidator.getPolicies(" + policyName + ", " + serviceName + ")");
+		}
+
+		List<RangerPolicy> policies = null;
+		try {
+			SearchFilter filter = new SearchFilter();
+			filter.setParam(SearchFilter.POLICY_NAME, policyName);
+			filter.setParam(SearchFilter.SERVICE_NAME, serviceName);
+			
+			policies = _store.getPolicies(filter);
+		} catch (Exception e) {
+			LOG.debug("Encountred exception while retrieving service from service store!", e);
+		}
+		
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("<== RangerValidator.getPolicies(" + policyName + ", " + serviceName + "): " + policies);
+		}
+		return policies;
+	}
+
+	Set<String> getAccessTypes(RangerServiceDef serviceDef) {
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("==> RangerValidator.getAccessTypes(" + serviceDef + ")");
+		}
+
+		Set<String> accessTypes = new HashSet<String>();
+		if (serviceDef == null) {
+			LOG.warn("serviceDef passed in was null!");
+		} else if (CollectionUtils.isEmpty(serviceDef.getAccessTypes())) {
+			LOG.warn("AccessTypeDef collection on serviceDef was null!");
+		} else {
+			for (RangerAccessTypeDef accessTypeDef : serviceDef.getAccessTypes()) {
+				if (accessTypeDef == null) {
+					LOG.warn("Access type def was null!");
+				} else {
+					String accessType = accessTypeDef.getName();
+					if (StringUtils.isBlank(accessType)) {
+						LOG.warn("Access type def name was null/empty/blank!");
+					} else {
+						accessTypes.add(accessType.toLowerCase());
+					}
+				}
+			}
+		}
+
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("<== RangerValidator.getAccessTypes(" + serviceDef + "): " + accessTypes);
+		}
+		return accessTypes;
+	}
+	
+	/**
+	 * This function exists to encapsulates the current behavior of code which treats and unspecified audit preference to mean audit is enabled.
+	 * @param policy
+	 * @return
+	 */
+	boolean getIsAuditEnabled(RangerPolicy policy) {
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("<== RangerValidator.getIsAuditEnabled(" + policy + ")");
+		}
+
+		boolean isEnabled = false;
+		if (policy == null) {
+			LOG.warn("policy was null!");
+		} else if (policy.getIsAuditEnabled() == null) {
+			isEnabled = true;
+		} else {
+			isEnabled = policy.getIsAuditEnabled();
+		}
+
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("<== RangerValidator.getIsAuditEnabled(" + policy + "): " + isEnabled);
+		}
+		return isEnabled;
+	}
+	
+	/**
+	 * Returns names of resource types set to lower-case to allow for case-insensitive comparison. 
+	 * @param serviceDef
+	 * @return
+	 */
+	Set<String> getMandatoryResourceNames(RangerServiceDef serviceDef) {
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("==> RangerValidator.getMandatoryResourceNames(" + serviceDef + ")");
+		}
+
+		Set<String> resourceNames = new HashSet<String>();
+		if (serviceDef == null) {
+			LOG.warn("serviceDef passed in was null!");
+		} else if (CollectionUtils.isEmpty(serviceDef.getResources())) {
+			LOG.warn("ResourceDef collection on serviceDef was null!");
+		} else {
+			for (RangerResourceDef resourceTypeDef : serviceDef.getResources()) {
+				if (resourceTypeDef == null) {
+					LOG.warn("resource type def was null!");
+				} else {
+					Boolean mandatory = resourceTypeDef.getMandatory();
+					if (mandatory != null && mandatory == true) {
+						String resourceName = resourceTypeDef.getName();
+						if (StringUtils.isBlank(resourceName)) {
+							LOG.warn("Resource def name was null/empty/blank!");
+						} else {
+							resourceNames.add(resourceName.toLowerCase());
+						}
+					}
+				}
+			}
+		}
+
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("<== RangerValidator.getMandatoryResourceNames(" + serviceDef + "): " + resourceNames);
+		}
+		return resourceNames;
+	}
+
+	Set<String> getAllResourceNames(RangerServiceDef serviceDef) {
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("==> RangerValidator.getAllResourceNames(" + serviceDef + ")");
+		}
+
+		Set<String> resourceNames = new HashSet<String>();
+		if (serviceDef == null) {
+			LOG.warn("serviceDef passed in was null!");
+		} else if (CollectionUtils.isEmpty(serviceDef.getResources())) {
+			LOG.warn("ResourceDef collection on serviceDef was null!");
+		} else {
+			for (RangerResourceDef resourceTypeDef : serviceDef.getResources()) {
+				if (resourceTypeDef == null) {
+					LOG.warn("resource type def was null!");
+				} else {
+					String resourceName = resourceTypeDef.getName();
+					if (StringUtils.isBlank(resourceName)) {
+						LOG.warn("Resource def name was null/empty/blank!");
+					} else {
+						resourceNames.add(resourceName.toLowerCase());
+					}
+				}
+			}
+		}
+
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("<== RangerValidator.getAllResourceNames(" + serviceDef + "): " + resourceNames);
+		}
+		return resourceNames;
+	}
+	
+	/**
+	 * Returns the resource-types defined on the policy converted to lowe-case
+	 * @param policy
+	 * @return
+	 */
+	Set<String> getPolicyResources(RangerPolicy policy) {
+		if (policy == null || policy.getResources() == null || policy.getResources().isEmpty()) {
+			return new HashSet<String>();
+		} else {
+			Set<String> result = new HashSet<String>();
+			for (String name : policy.getResources().keySet()) {
+				result.add(name.toLowerCase());
+			}
+			return result;
+		}
+	}
+
+	Map<String, String> getValidationRegExes(RangerServiceDef serviceDef) {
+		if (serviceDef == null || CollectionUtils.isEmpty(serviceDef.getResources())) {
+			return new HashMap<String, String>();
+		} else {
+			Map<String, String> result = new HashMap<String, String>();
+			for (RangerResourceDef resourceDef : serviceDef.getResources()) {
+				if (resourceDef == null) {
+					LOG.warn("A resource def in resource def collection is null");
+				} else {
+					String name = resourceDef.getName();
+					String regEx = resourceDef.getValidationRegEx();
+					if (StringUtils.isBlank(name)) {
+						LOG.warn("resource name is null/empty/blank");
+					} else if (StringUtils.isBlank(regEx)) {
+						LOG.debug("validation regex is null/empty/blank");
+					} else {
+						result.put(name, regEx);
+					}
+				}
+			}
+			return result;
+		}
+	}
+	
+	int getEnumDefaultIndex(RangerEnumDef enumDef) {
+		int index;
+		if (enumDef == null) {
+			index = -1;
+		} else if (enumDef.getDefaultIndex() == null) {
+			index = 0;
+		} else {
+			index = enumDef.getDefaultIndex();
+		}
+		return index;
+	}
+
+	Collection<String> getImpliedGrants(RangerAccessTypeDef def) {
+		if (def == null) {
+			return null;
+		} else if (CollectionUtils.isEmpty(def.getImpliedGrants())) {
+			return new ArrayList<String>();
+		} else {
+			List<String> result = new ArrayList<String>(def.getImpliedGrants().size());
+			for (String name : def.getImpliedGrants()) {
+				if (StringUtils.isBlank(name)) {
+					result.add(name); // could be null!
+				} else {
+					result.add(name.toLowerCase());
+				}
+			}
+			return result;
+		}
+	}
+
+	/**
+	 * Returns a copy of the policy resource map where all keys (resource-names) are lowercase
+	 * @param input
+	 * @return
+	 */
+	Map<String, RangerPolicyResource> getPolicyResourceWithLowerCaseKeys(Map<String, RangerPolicyResource> input) {
+		if (input == null) {
+			return null;
+		}
+		Map<String, RangerPolicyResource> output = new HashMap<String, RangerPolicyResource>(input.size());
+		for (Map.Entry<String, RangerPolicyResource> entry : input.entrySet()) {
+			output.put(entry.getKey().toLowerCase(), entry.getValue());
+		}
+		return output;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerValidatorFactory.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerValidatorFactory.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerValidatorFactory.java
new file mode 100644
index 0000000..f72e8df
--- /dev/null
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerValidatorFactory.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF 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.apache.ranger.plugin.model.validation;
+
+import org.apache.ranger.plugin.store.ServiceStore;
+
+public class RangerValidatorFactory {
+	public RangerServiceValidator getServiceValidator(ServiceStore store) {
+		return new RangerServiceValidator(store);
+	}
+
+	public RangerPolicyValidator getPolicyValidator(ServiceStore store) {
+		return new RangerPolicyValidator(store);
+	}
+
+	public RangerServiceDefValidator getServiceDefValidator(ServiceStore store) {
+		return new RangerServiceDefValidator(store);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/ValidationFailureDetails.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/ValidationFailureDetails.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/ValidationFailureDetails.java
new file mode 100644
index 0000000..015203a
--- /dev/null
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/ValidationFailureDetails.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF 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.apache.ranger.plugin.model.validation;
+
+import java.util.Objects;
+
+public class ValidationFailureDetails {
+
+	final String _fieldName;
+	final String _subFieldName;
+	final boolean _missing;
+	final boolean _semanticError;
+	final boolean _internalError;
+	final String _reason;
+	
+	public ValidationFailureDetails(String fieldName, String subFieldName, boolean missing, boolean semanticError, boolean internalError, String reason) {
+		_missing = missing;
+		_semanticError = semanticError;
+		_internalError = internalError;
+		_fieldName = fieldName;
+		_subFieldName = subFieldName;
+		_reason = reason;
+	}
+
+	public String getFieldName() {
+		return _fieldName;
+	}
+
+	public boolean isMissingRequiredValue() {
+		return _missing;
+	}
+
+	public boolean isSemanticallyIncorrect() {
+		return _semanticError;
+	}
+	
+	String getType() {
+		if (_missing) return "missing";
+		if (_semanticError) return "semantically incorrect";
+		if (_internalError) return "internal error";
+		return "";
+	}
+
+	public String getSubFieldName() {
+		return _subFieldName;
+	}
+	
+	@Override
+	public String toString() {
+		return String.format("Field[%s]%s is %s: reason[%s]", 
+				_fieldName, 
+				_subFieldName == null ? "" : ", subField[" + _subFieldName + "]",
+				getType(), _reason);
+	}
+	
+	@Override
+	public int hashCode() {
+		return Objects.hash(_fieldName, _subFieldName, _missing, _semanticError, _internalError, _reason);
+	}
+	
+	@Override
+	public boolean equals(Object obj) {
+		if (obj == null || !(obj instanceof ValidationFailureDetails)) {
+			return false;
+		}
+		ValidationFailureDetails that = (ValidationFailureDetails)obj;
+		return Objects.equals(_fieldName, that._fieldName) && 
+				Objects.equals(_subFieldName, that._subFieldName) && 
+				Objects.equals(_reason, that._reason) && 
+				_internalError == that._internalError &&
+				_missing == that._missing &&
+				_semanticError == that._semanticError;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/7bb68687/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/ValidationFailureDetailsBuilder.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/ValidationFailureDetailsBuilder.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/ValidationFailureDetailsBuilder.java
new file mode 100644
index 0000000..3a57341
--- /dev/null
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/ValidationFailureDetailsBuilder.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF 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.apache.ranger.plugin.model.validation;
+
+public class ValidationFailureDetailsBuilder {
+	private String _fieldName;
+	private boolean _missing;
+	private boolean _semanticError;
+	private String _reason;
+	private String _subFieldName;
+	private boolean _internalError;
+	
+	ValidationFailureDetailsBuilder becauseOf(String aReason) {
+		_reason = aReason;
+		return this;
+	}
+	
+	ValidationFailureDetailsBuilder isMissing() {
+		_missing = true;
+		return this;
+	}
+	
+	ValidationFailureDetailsBuilder isSemanticallyIncorrect() {
+		_semanticError = true;
+		return this;
+	}
+	
+	ValidationFailureDetailsBuilder field(String fieldName) {
+		_fieldName = fieldName;
+		return this;
+	}
+	
+	ValidationFailureDetails build() {
+		return new ValidationFailureDetails(_fieldName, _subFieldName, _missing, _semanticError, _internalError, _reason);
+	}
+
+	ValidationFailureDetailsBuilder subField(String missingParameter) {
+		_subFieldName = missingParameter;
+		return this;
+	}
+
+	ValidationFailureDetailsBuilder isAnInternalError() {
+		_internalError = true;
+		return this;
+	}
+
+}