Repository: incubator-ranger
Updated Branches:
  refs/heads/master 4d1abc89c -> 6e9f2a3b5


RANGER-299 Service def validations; RANGER-304 validation does several checks 
in case-insensitive manner

Conflicts:
        
security-admin/src/main/java/org/apache/ranger/rest/RangerServiceValidator.java

Signed-off-by: Madhan Neethiraj <[email protected]>


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

Branch: refs/heads/master
Commit: 6e9f2a3b5a9cc2a04927ca6a99f8c3ec93f1891b
Parents: 4d1abc8
Author: Alok Lal <[email protected]>
Authored: Thu Mar 5 14:55:18 2015 -0800
Committer: Madhan Neethiraj <[email protected]>
Committed: Thu Mar 12 16:13:03 2015 -0700

----------------------------------------------------------------------
 .../ranger/rest/RangerPolicyValidator.java      |  26 +-
 .../ranger/rest/RangerServiceDefValidator.java  | 365 +++++++++++++++++++
 .../ranger/rest/RangerServiceValidator.java     |  31 +-
 .../org/apache/ranger/rest/RangerValidator.java |  73 +++-
 .../ranger/rest/RangerValidatorFactory.java     |   4 +
 .../org/apache/ranger/rest/ServiceREST.java     |   6 +
 .../ranger/rest/TestRangerPolicyValidator.java  |  15 +-
 .../rest/TestRangerServiceDefValidator.java     | 353 ++++++++++++++++++
 .../apache/ranger/rest/TestRangerValidator.java | 162 +++++++-
 .../rest/TestServiceRESTForValidation.java      | 133 ++++++-
 .../apache/ranger/rest/ValidationTestUtils.java |  60 +++
 11 files changed, 1167 insertions(+), 61 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/6e9f2a3b/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
index 941bb21..281b32d 100644
--- 
a/security-admin/src/main/java/org/apache/ranger/rest/RangerPolicyValidator.java
+++ 
b/security-admin/src/main/java/org/apache/ranger/rest/RangerPolicyValidator.java
@@ -29,7 +29,7 @@ public class RangerPolicyValidator extends RangerValidator {
 
        public void validate(RangerPolicy policy, Action action) throws 
Exception {
                if(LOG.isDebugEnabled()) {
-                       LOG.debug(String.format("==> 
RangerValidator.validate(%s, %s)", policy, action));
+                       LOG.debug(String.format("==> 
RangerPolicyValidator.validate(%s, %s)", policy, action));
                }
 
                List<ValidationFailureDetails> failures = new 
ArrayList<ValidationFailureDetails>();
@@ -42,7 +42,7 @@ public class RangerPolicyValidator extends RangerValidator {
                        }
                } finally {
                        if(LOG.isDebugEnabled()) {
-                               LOG.debug(String.format("<== 
RangerValidator.validate(%s, %s): %s, reason[%s]", policy, action, valid, 
message));
+                               LOG.debug(String.format("<== 
RangerPolicyValidator.validate(%s, %s): %s, reason[%s]", policy, action, valid, 
message));
                        }
                }
        }
@@ -151,7 +151,7 @@ public class RangerPolicyValidator extends RangerValidator {
                                                failures.add(new 
ValidationFailureDetailsBuilder()
                                                        .field("id/name")
                                                        
.isSemanticallyIncorrect()
-                                                       .becauseOf("id/name 
conflict: policy already exists with name[" + policyName + "], its id is[" + 
policies.iterator().next().getId() + "]")
+                                                       .becauseOf("id/name 
conflict: another policy already exists with name[" + policyName + "], its id 
is[" + policies.iterator().next().getId() + "]")
                                                        .build());
                                                valid = false;
                                        }
@@ -396,17 +396,15 @@ public class RangerPolicyValidator extends 
RangerValidator {
                                        .becauseOf("policy items access type's 
name was null/empty/blank")
                                        .build());
                                valid = false;
-                       } else {
-                               if (!accessTypes.contains(accessType)) {
-                                       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;
-                               }
+                       } 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

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/6e9f2a3b/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
new file mode 100644
index 0000000..a84f68a
--- /dev/null
+++ 
b/security-admin/src/main/java/org/apache/ranger/rest/RangerServiceDefValidator.java
@@ -0,0 +1,365 @@
+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/6e9f2a3b/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
index 11e2682..8e02f25 100644
--- 
a/security-admin/src/main/java/org/apache/ranger/rest/RangerServiceValidator.java
+++ 
b/security-admin/src/main/java/org/apache/ranger/rest/RangerServiceValidator.java
@@ -42,18 +42,21 @@ public class RangerServiceValidator extends RangerValidator 
{
 
        public void validate(RangerService service, Action action) throws 
Exception {
                if(LOG.isDebugEnabled()) {
-                       LOG.debug("==> RangerValidator.validate(" + service + 
")");
+                       LOG.debug(String.format("==> 
RangerServiceValidator.validate(%s, %s)", service, action));
                }
 
                List<ValidationFailureDetails> failures = new 
ArrayList<ValidationFailureDetails>();
-               if (isValid(service, action, failures)) {
+               boolean valid = isValid(service, action, failures);
+               String message = "";
+               try {
+                       if (!valid) {
+                               message = serializeFailures(failures);
+                               throw new Exception(message);
+                       }
+               } finally {
                        if(LOG.isDebugEnabled()) {
-                               LOG.debug("<== RangerValidator.validate(" + 
service + "): valid");
+                               LOG.debug(String.format("<== 
RangerServiceValidator.validate(%s, %s): %s, reason[%s]", service, action, 
valid, message));
                        }
-               } else {
-                       String message = serializeFailures(failures);
-                       LOG.debug("<== RangerValidator.validate(" + service + 
"): invalid, reason[" + message + "]");
-                       throw new Exception(message);
                }
        }
        
@@ -66,7 +69,7 @@ public class RangerServiceValidator extends RangerValidator {
                if (action != Action.DELETE) {
                        failures.add(new ValidationFailureDetailsBuilder()
                                .isAnInternalError()
-                               .becauseOf("isValid(Long) is only supported for 
DELETE")
+                               .becauseOf("unsupported action[" + action + "]; 
isValid(Long) is only supported for DELETE")
                                .build());
                        valid = false;
                } else if (id == null) {
@@ -133,7 +136,7 @@ public class RangerServiceValidator extends RangerValidator 
{
                        boolean nameSpecified = StringUtils.isNotBlank(name);
                        RangerServiceDef serviceDef = null;
                        if (!nameSpecified) {
-                               String message = "service name was 
null/empty/blank[" + name + "]"; 
+                               String message = "service name[" + name + "] 
was null/empty/blank"; 
                                LOG.debug(message);
                                failures.add(new 
ValidationFailureDetailsBuilder()
                                        .field("name")
@@ -147,14 +150,14 @@ public class RangerServiceValidator extends 
RangerValidator {
                                        failures.add(new 
ValidationFailureDetailsBuilder()
                                                .field("name")
                                                .isSemanticallyIncorrect()
-                                               .becauseOf("service already 
exists with name[" + name + "]")
+                                               .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: 
service already exists with name[" + name + "], its id is [" + 
otherService.getId() + "]")
+                                               .becauseOf("id/name conflict: 
another service already exists with name[" + name + "], its id is [" + 
otherService.getId() + "]")
                                                .build());
                                        valid = false;
                                }
@@ -165,7 +168,7 @@ public class RangerServiceValidator extends RangerValidator 
{
                                failures.add(new 
ValidationFailureDetailsBuilder()
                                        .field("type")
                                        .isMissing()
-                                       .becauseOf("service def was 
null/empty/blank")
+                                       .becauseOf("service def [" + type + "] 
was null/empty/blank")
                                        .build());
                                valid = false;
                        } else {
@@ -174,7 +177,7 @@ public class RangerServiceValidator extends RangerValidator 
{
                                        failures.add(new 
ValidationFailureDetailsBuilder()
                                                .field("type")
                                                .isSemanticallyIncorrect()
-                                               .becauseOf("service def not 
found for type[" + type + "]")
+                                               .becauseOf("service def named[" 
+ type + "] not found")
                                                .build());
                                        valid = false;
                                }
@@ -188,7 +191,7 @@ public class RangerServiceValidator extends RangerValidator 
{
                                                .field("configuration")
                                                
.subField(missingParameters.iterator().next()) // we return any one parameter!
                                                .isMissing()
-                                               .becauseOf("required 
configuration parameter is missing")
+                                               .becauseOf("required 
configuration parameter is missing; missing parameters: " + missingParameters)
                                                .build());
                                        valid = false;
                                }

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/6e9f2a3b/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
index b6948dc..cec40fd 100644
--- a/security-admin/src/main/java/org/apache/ranger/rest/RangerValidator.java
+++ b/security-admin/src/main/java/org/apache/ranger/rest/RangerValidator.java
@@ -21,6 +21,7 @@ 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;
@@ -36,6 +37,7 @@ 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.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;
@@ -149,6 +151,24 @@ public abstract class RangerValidator {
                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()) {
@@ -262,7 +282,7 @@ public abstract class RangerValidator {
                                        if (StringUtils.isBlank(accessType)) {
                                                LOG.warn("Access type def name 
was null/empty/blank!");
                                        } else {
-                                               accessTypes.add(accessType);
+                                               
accessTypes.add(accessType.toLowerCase());
                                        }
                                }
                        }
@@ -299,6 +319,11 @@ public abstract class RangerValidator {
                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 + ")");
@@ -320,7 +345,7 @@ public abstract class RangerValidator {
                                                if 
(StringUtils.isBlank(resourceName)) {
                                                        LOG.warn("Resource def 
name was null/empty/blank!");
                                                } else {
-                                                       
resourceNames.add(resourceName);
+                                                       
resourceNames.add(resourceName.toLowerCase());
                                                }
                                        }
                                }
@@ -352,7 +377,7 @@ public abstract class RangerValidator {
                                        if (StringUtils.isBlank(resourceName)) {
                                                LOG.warn("Resource def name was 
null/empty/blank!");
                                        } else {
-                                               resourceNames.add(resourceName);
+                                               
resourceNames.add(resourceName.toLowerCase());
                                        }
                                }
                        }
@@ -364,11 +389,20 @@ public abstract class RangerValidator {
                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 {
-                       return policy.getResources().keySet();
+                       Set<String> result = new HashSet<String>();
+                       for (String name : policy.getResources().keySet()) {
+                               result.add(name.toLowerCase());
+                       }
+                       return result;
                }
        }
 
@@ -395,4 +429,35 @@ public abstract class RangerValidator {
                        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;
+               }
+       }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/6e9f2a3b/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
index 01b0a7e..025595d 100644
--- 
a/security-admin/src/main/java/org/apache/ranger/rest/RangerValidatorFactory.java
+++ 
b/security-admin/src/main/java/org/apache/ranger/rest/RangerValidatorFactory.java
@@ -30,4 +30,8 @@ public class RangerValidatorFactory {
        public RangerPolicyValidator getPolicyValidator(ServiceDBStore store) {
                return new RangerPolicyValidator(store);
        }
+
+       public RangerServiceDefValidator getServiceDefValidator(ServiceDBStore 
store) {
+               return new RangerServiceDefValidator(store);
+       }
 }

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/6e9f2a3b/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 be52892..8f41288 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
@@ -119,6 +119,8 @@ public class ServiceREST {
                RangerServiceDef ret = null;
 
                try {
+                       RangerServiceDefValidator validator = 
validatorFactory.getServiceDefValidator(svcStore);
+                       validator.validate(serviceDef, Action.CREATE);
                        ret = svcStore.createServiceDef(serviceDef);
                } catch(Exception excp) {
                        LOG.error("createServiceDef(" + serviceDef + ") 
failed", excp);
@@ -145,6 +147,8 @@ public class ServiceREST {
                RangerServiceDef ret = null;
 
                try {
+                       RangerServiceDefValidator validator = 
validatorFactory.getServiceDefValidator(svcStore);
+                       validator.validate(serviceDef, Action.UPDATE);
                        ret = svcStore.updateServiceDef(serviceDef);
                } catch(Exception excp) {
                        LOG.error("updateServiceDef(" + serviceDef + ") 
failed", excp);
@@ -169,6 +173,8 @@ public class ServiceREST {
                }
 
                try {
+                       RangerServiceDefValidator validator = 
validatorFactory.getServiceDefValidator(svcStore);
+                       validator.validate(id, Action.DELETE);
                        svcStore.deleteServiceDef(id);
                } catch(Exception excp) {
                        LOG.error("deleteServiceDef(" + id + ") failed", excp);

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/6e9f2a3b/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
index 4e15753..c3fdf30 100644
--- 
a/security-admin/src/test/java/org/apache/ranger/rest/TestRangerPolicyValidator.java
+++ 
b/security-admin/src/test/java/org/apache/ranger/rest/TestRangerPolicyValidator.java
@@ -45,20 +45,20 @@ public class TestRangerPolicyValidator {
                                "groups", new String[] {"group1", "group2"},
                                "accesses", new String[] { "r", "w" },
                                "isAllowed", new Boolean[] { true, true }),
-                       ImmutableMap.of(   // no users
+                       ImmutableMap.of(   // no users, access type different 
case
                                "groups", new String[] {"group3", "group4"},
-                               "accesses", new String[]{"w", "x"}, 
+                               "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
+                       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" };
+       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)
        
        final Object[][] resourceDefData = new Object[][] {
@@ -69,7 +69,8 @@ public class TestRangerPolicyValidator {
        
        final Map<String, String[]> policyResourceMap_good = ImmutableMap.of(
                        "db", new String[] { "db1", "db2" },
-                       "tbl", new String[] { "tbl1", "tbl2" } );
+                       "TBL", new String[] { "tbl1", "tbl2" } ); // case 
should not matter
+       
        final Map<String, String[]> policyResourceMap_bad = ImmutableMap.of(
                        "db", new String[] { "db1", "db2" },            // 
mandatory "tbl" missing
                        "col", new String[] { "col12", "col 1" },       // 
wrong format of value for "col"
@@ -424,9 +425,9 @@ public class TestRangerPolicyValidator {
        public void test_isValidPolicyItemAccess_happyPath() {
                
                RangerPolicyItemAccess access = 
mock(RangerPolicyItemAccess.class);
-               when(access.getType()).thenReturn("anAccess"); // valid
+               when(access.getType()).thenReturn("an-Access"); // valid
 
-               Set<String> validAccesses = Sets.newHashSet(new String[] { 
"anAccess", "anotherAccess" });
+               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 } ) {

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/6e9f2a3b/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
new file mode 100644
index 0000000..b621673
--- /dev/null
+++ 
b/security-admin/src/test/java/org/apache/ranger/rest/TestRangerServiceDefValidator.java
@@ -0,0 +1,353 @@
+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.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/6e9f2a3b/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
index d3ee6d6..7da6672 100644
--- 
a/security-admin/src/test/java/org/apache/ranger/rest/TestRangerValidator.java
+++ 
b/security-admin/src/test/java/org/apache/ranger/rest/TestRangerValidator.java
@@ -26,26 +26,32 @@ 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.when;
+import static org.mockito.Mockito.*;
 
 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.Action;
 import org.junit.Before;
 import org.junit.Test;
 
+import com.google.common.collect.Maps;
+
 public class TestRangerValidator {
 
        static class RangerValidatorForTest extends RangerValidator {
@@ -238,13 +244,14 @@ public class TestRangerValidator {
                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" };
+               String[] names = new String[] { null, "", "a", "  ", "b ", "    
        ", " C", "      D       " };
                accessTypeDefs.addAll(_utils.createAccessTypeDefs(names));
                accessTypes = _validator.getAccessTypes(serviceDef);
-               assertEquals(3, accessTypes.size());
+               assertEquals(4, accessTypes.size());
                assertTrue(accessTypes.contains("a"));
                assertTrue(accessTypes.contains("b "));
                assertTrue(accessTypes.contains(" c"));
+               assertTrue(accessTypes.contains("       d       "));
        }
        
        @Test
@@ -270,22 +277,24 @@ public class TestRangerValidator {
                
                // 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 }, // mandatory field false
-                               { "d", true }, // all good
+                               { "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"));
+               assertTrue(accessTypes.contains("d")); // name should come back 
lower case
                
                accessTypes = _validator.getAllResourceNames(serviceDef);
-               assertEquals(4, accessTypes.size());
+               assertEquals(5, accessTypes.size());
                assertTrue(accessTypes.contains("b"));
                assertTrue(accessTypes.contains("c"));
+               assertTrue(accessTypes.contains("e"));
        }
 
        @Test
@@ -327,6 +336,137 @@ public class TestRangerValidator {
                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/6e9f2a3b/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 da15ffa..d112b83 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
@@ -37,6 +37,7 @@ import org.apache.ranger.biz.ServiceDBStore;
 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.rest.RangerValidator.Action;
 import org.junit.Before;
 import org.junit.Test;
@@ -51,6 +52,7 @@ public class TestServiceRESTForValidation {
                // inject out store in it
                _store = mock(ServiceDBStore.class);
                _serviceRest.svcStore = _store;
+               
                // and our validator factory
                _factory = mock(RangerValidatorFactory.class);
                _serviceValidator = mock(RangerServiceValidator.class);
@@ -58,6 +60,9 @@ public class TestServiceRESTForValidation {
                _policyValidator = mock(RangerPolicyValidator.class);
                
when(_factory.getPolicyValidator(_store)).thenReturn(_policyValidator);
                _serviceRest.validatorFactory = _factory;
+               _serviceDefValidator = mock(RangerServiceDefValidator.class);
+               
when(_factory.getServiceDefValidator(_store)).thenReturn(_serviceDefValidator);
+
                // and other things that are needed for service rest to work 
correctly
                _restErrorUtil = mock(RESTErrorUtil.class);
                WebApplicationException webApplicationException = new 
WebApplicationException();
@@ -85,7 +90,7 @@ public class TestServiceRESTForValidation {
                        // 
                        _serviceRest.updateService(_service);
                        verify(_serviceValidator).validate(_service, 
Action.UPDATE);
-
+       
                        _serviceRest.deleteService(3L);
                        verify(_serviceValidator).validate(3L, Action.DELETE);
                } catch (Throwable t) {
@@ -93,7 +98,7 @@ public class TestServiceRESTForValidation {
                        fail("Unexpected exception thrown!");
                }
        }
-
+       
        @Test
        public final void testService_storeFailure() throws Exception {
                /*
@@ -283,14 +288,120 @@ public class TestServiceRESTForValidation {
                        fail("Unexpected exception!");
                }
        }
+
+       @Test
+       public final void testServiceDef_happyPath() throws Exception {
+               /*
+                * Creation should succeed if neither validator nor dbstore 
throw exception.
+                * - by default mocks return null for unspecified methods, so 
no additional mocking needed.
+                * - We just assert that validator is called with right set of 
arguments.
+                * - db store would also have been excercised but that is not 
the focus of this test, so we don't assert about it!!
+                */
+               try {
+                       _serviceRest.createServiceDef(_serviceDef);
+                       verify(_serviceDefValidator).validate(_serviceDef, 
Action.CREATE);
+                       // 
+                       _serviceRest.updateServiceDef(_serviceDef);
+                       verify(_serviceDefValidator).validate(_serviceDef, 
Action.UPDATE);
+
+                       _serviceRest.deleteServiceDef(3L);
+                       verify(_serviceDefValidator).validate(3L, 
Action.DELETE);
+               } catch (Throwable t) {
+                       t.printStackTrace();
+                       fail("Unexpected exception thrown!");
+               }
+       }
        
-       RangerValidatorFactory _factory;
-       RangerServiceValidator _serviceValidator;
-       RangerPolicyValidator _policyValidator;
-       ServiceDBStore _store;
-       ServiceREST _serviceRest;
-       RangerService _service;
-       RangerPolicy _policy;
-       Exception _exception;
-       RESTErrorUtil _restErrorUtil;
+       @Test
+       public void testServiveDef_validatorFailure() throws Exception {
+               
+               
doThrow(_exception).when(_serviceDefValidator).validate(_serviceDef, 
Action.CREATE);
+               try {
+                       _serviceRest.createServiceDef(_serviceDef);
+                       fail("Should have thrown exception!");
+               } catch (WebApplicationException t) {
+                       verify(_serviceDefValidator).validate(_serviceDef, 
Action.CREATE);
+                       verify(_store, never()).createServiceDef(_serviceDef);
+               } catch (Throwable t) {
+                       LOG.debug(t);
+                       fail("Unexpected exception!");
+               }
+
+               
doThrow(_exception).when(_serviceDefValidator).validate(_serviceDef, 
Action.UPDATE);
+               try {
+                       _serviceRest.updateServiceDef(_serviceDef);
+                       fail("Should have thrown exception!");
+               } catch (WebApplicationException t) {
+                       verify(_serviceDefValidator).validate(_serviceDef, 
Action.UPDATE);
+                       verify(_store, never()).updateServiceDef(_serviceDef);
+               } catch (Throwable t) {
+                       LOG.debug(t);
+                       fail("Unexpected exception!");
+               }
+
+               doThrow(_exception).when(_serviceDefValidator).validate(4L, 
Action.DELETE);
+               try {
+                       _serviceRest.deleteServiceDef(4L);
+                       fail("Should have thrown exception!");
+               } catch (WebApplicationException t) {
+                       verify(_serviceDefValidator).validate(4L, 
Action.DELETE);
+                       verify(_store, never()).deleteServiceDef(4L);
+               } catch (Throwable t) {
+                       LOG.debug(t);
+                       fail("Unexpected exception!");
+               }
+       }
+       
+       @Test
+       public void testServiceDef_storeFailure() throws Exception {
+               doThrow(_exception).when(_store).createServiceDef(_serviceDef);
+               try {
+                       _serviceRest.createServiceDef(_serviceDef);
+                       fail("Should have thrown exception!");
+               } catch (WebApplicationException e) {
+                       verify(_serviceDefValidator).validate(_serviceDef, 
Action.CREATE);
+                       verify(_store).createServiceDef(_serviceDef);
+               } catch (Throwable t) {
+                       LOG.debug(t);
+                       fail("Unexpected exception!");
+               }
+               
+               doThrow(_exception).when(_store).updateServiceDef(_serviceDef);
+               try {
+                       _serviceRest.updateServiceDef(_serviceDef);
+                       fail("Should have thrown exception!");
+               } catch (WebApplicationException e) {
+                       verify(_serviceDefValidator).validate(_serviceDef, 
Action.UPDATE);
+                       verify(_store).updateServiceDef(_serviceDef);
+               } catch (Throwable t) {
+                       LOG.debug(t);
+                       fail("Unexpected exception!");
+               }
+               
+               doThrow(_exception).when(_store).deleteServiceDef(5L);
+               try {
+                       _serviceRest.deleteServiceDef(5L);
+                       fail("Should have thrown exception!");
+               } catch (WebApplicationException e) {
+                       verify(_serviceDefValidator).validate(5L, 
Action.DELETE);
+                       verify(_store).deleteServiceDef(5L);
+               } catch (Throwable t) {
+                       LOG.debug(t);
+                       fail("Unexpected exception!");
+               }
+       }
+
+       private RangerValidatorFactory _factory;
+       private RangerServiceValidator _serviceValidator;
+       private RangerPolicyValidator _policyValidator;
+       private RangerServiceDefValidator _serviceDefValidator;
+
+       private ServiceDBStore _store;
+       private ServiceREST _serviceRest;
+       private Exception _exception;
+       private RESTErrorUtil _restErrorUtil;
+
+       private RangerService _service;
+       private RangerPolicy _policy;
+       private RangerServiceDef _serviceDef;
 }

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/6e9f2a3b/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
index b734763..6c71502 100644
--- 
a/security-admin/src/test/java/org/apache/ranger/rest/ValidationTestUtils.java
+++ 
b/security-admin/src/test/java/org/apache/ranger/rest/ValidationTestUtils.java
@@ -37,6 +37,8 @@ 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;
 
@@ -119,6 +121,30 @@ public class ValidationTestUtils {
                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>();
@@ -249,4 +275,38 @@ public class ValidationTestUtils {
                }
                return resourceMap;
        }
+
+       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;
+       }
 }

Reply via email to