You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@storm.apache.org by bo...@apache.org on 2015/10/15 20:18:08 UTC
[3/5] storm git commit: revision based on suggestions
revision based on suggestions
Project: http://git-wip-us.apache.org/repos/asf/storm/repo
Commit: http://git-wip-us.apache.org/repos/asf/storm/commit/b5cb2ecd
Tree: http://git-wip-us.apache.org/repos/asf/storm/tree/b5cb2ecd
Diff: http://git-wip-us.apache.org/repos/asf/storm/diff/b5cb2ecd
Branch: refs/heads/master
Commit: b5cb2ecdad9d023e9691d5ef5f7dc4aaef7dca75
Parents: c7f0882
Author: Boyang Jerry Peng <je...@yahoo-inc.com>
Authored: Thu Oct 15 10:18:14 2015 -0500
Committer: Boyang Jerry Peng <je...@yahoo-inc.com>
Committed: Thu Oct 15 11:16:50 2015 -0500
----------------------------------------------------------------------
.../storm/validation/ConfigValidation.java | 228 +++++++++++--------
.../validation/ConfigValidationAnnotations.java | 22 +-
.../jvm/backtype/storm/TestConfigValidate.java | 13 +-
3 files changed, 152 insertions(+), 111 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/storm/blob/b5cb2ecd/storm-core/src/jvm/backtype/storm/validation/ConfigValidation.java
----------------------------------------------------------------------
diff --git a/storm-core/src/jvm/backtype/storm/validation/ConfigValidation.java b/storm-core/src/jvm/backtype/storm/validation/ConfigValidation.java
index 2e4470c..b9244ef 100644
--- a/storm-core/src/jvm/backtype/storm/validation/ConfigValidation.java
+++ b/storm-core/src/jvm/backtype/storm/validation/ConfigValidation.java
@@ -24,6 +24,8 @@ import org.slf4j.LoggerFactory;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
@@ -37,11 +39,9 @@ public class ConfigValidation {
private static final Logger LOG = LoggerFactory.getLogger(ConfigValidation.class);
public static abstract class Validator {
- public abstract void validateField(String name, Object o);
- }
-
- public abstract static class TypeValidator {
- public abstract void validateField(String name, Class type, Object o);
+ public Validator(Map<String, Object> params) {}
+ public Validator() {}
+ public abstract void validateField(String name, Object o) throws InstantiationException, IllegalAccessException;
}
/**
@@ -65,9 +65,20 @@ public class ConfigValidation {
/**
* Validates basic types
*/
- public static class SimpleTypeValidator extends TypeValidator {
+ public static class SimpleTypeValidator extends Validator {
+
+ private Class type;
- public void validateField(String name, Class type, Object o) {
+ public SimpleTypeValidator(Map<String, Object> params) {
+ this.type = (Class) params.get(ConfigValidationAnnotations.ValidatorParams.TYPE);
+ }
+
+ @Override
+ public void validateField(String name, Object o) {
+ validateField(name, this.type, o);
+ }
+
+ public static void validateField(String name, Class type, Object o) {
if (o == null) {
return;
}
@@ -82,8 +93,7 @@ public class ConfigValidation {
@Override
public void validateField(String name, Object o) {
- SimpleTypeValidator validator = new SimpleTypeValidator();
- validator.validateField(name, String.class, o);
+ SimpleTypeValidator.validateField(name, String.class, o);
}
}
@@ -91,8 +101,7 @@ public class ConfigValidation {
@Override
public void validateField(String name, Object o) {
- SimpleTypeValidator validator = new SimpleTypeValidator();
- validator.validateField(name, Boolean.class, o);
+ SimpleTypeValidator.validateField(name, Boolean.class, o);
}
}
@@ -100,8 +109,7 @@ public class ConfigValidation {
@Override
public void validateField(String name, Object o) {
- SimpleTypeValidator validator = new SimpleTypeValidator();
- validator.validateField(name, Number.class, o);
+ SimpleTypeValidator.validateField(name, Number.class, o);
}
}
@@ -109,8 +117,7 @@ public class ConfigValidation {
@Override
public void validateField(String name, Object o) {
- SimpleTypeValidator validator = new SimpleTypeValidator();
- validator.validateField(name, Double.class, o);
+ SimpleTypeValidator.validateField(name, Double.class, o);
}
}
@@ -168,8 +175,7 @@ public class ConfigValidation {
return;
}
//check if iterable
- SimpleTypeValidator isIterable = new SimpleTypeValidator();
- isIterable.validateField(name, Iterable.class, field);
+ SimpleTypeValidator.validateField(name, Iterable.class, field);
HashSet<Object> objectSet = new HashSet<Object>();
for (Object o : (Iterable) field) {
if (objectSet.contains(o)) {
@@ -190,18 +196,10 @@ public class ConfigValidation {
@Override
public void validateField(String name, Object o) {
- if (o == null) {
+ if (o == null || o instanceof String) {
+ // A null value or a String value is acceptable
return;
}
- if (o instanceof String) {
- return;
- }
- //check if iterable
- SimpleTypeValidator isIterable = new SimpleTypeValidator();
- try {
- isIterable.validateField(name, Iterable.class, o);
- } catch (Exception ex) {
- }
this.fv.validateField(name, o);
}
}
@@ -263,10 +261,20 @@ public class ConfigValidation {
/**
* Validates each entry in a list
*/
- public static class ListEntryTypeValidator extends TypeValidator {
+ public static class ListEntryTypeValidator extends Validator {
+
+ private Class type;
+
+ public ListEntryTypeValidator(Map<String, Object> params) {
+ this.type = (Class) params.get(ConfigValidationAnnotations.ValidatorParams.TYPE);
+ }
@Override
- public void validateField(String name, Class type, Object o) {
+ public void validateField(String name, Object o) {
+ validateField(name, this.type, o);
+ }
+
+ public static void validateField(String name, Class type, Object o) {
ConfigValidationUtils.NestableFieldValidator validator = ConfigValidationUtils.listFv(type, false);
validator.validateField(name, o);
}
@@ -276,15 +284,26 @@ public class ConfigValidation {
* Validates each entry in a list against a list of custom Validators
* Each validator in the list of validators must inherit or be an instance of Validator class
*/
- public static class ListEntryCustomValidator {
+ public static class ListEntryCustomValidator extends Validator{
- public void validateField(String name, Class[] validators, Object o) throws IllegalAccessException, InstantiationException {
+ private Class[] entryValidators;
+
+ public ListEntryCustomValidator(Map<String, Object> params) {
+ this.entryValidators = (Class[]) params.get(ConfigValidationAnnotations.ValidatorParams.ENTRY_VALIDATOR_CLASSES);
+ }
+
+ @Override
+ public void validateField(String name, Object o) throws InstantiationException, IllegalAccessException {
+
+ validateField(name, this.entryValidators, o);
+ }
+
+ public static void validateField(String name, Class[] validators, Object o) throws IllegalAccessException, InstantiationException {
if (o == null) {
return;
}
//check if iterable
- SimpleTypeValidator isIterable = new SimpleTypeValidator();
- isIterable.validateField(name, Iterable.class, o);
+ SimpleTypeValidator.validateField(name, Iterable.class, o);
for (Object entry : (Iterable) o) {
for (Class validator : validators) {
Object v = validator.newInstance();
@@ -301,9 +320,22 @@ public class ConfigValidation {
/**
* validates each key and value in a map of a certain type
*/
- public static class MapEntryTypeValidator {
+ public static class MapEntryTypeValidator extends Validator{
+
+ private Class keyType;
+ private Class valueType;
- public void validateField(String name, Class keyType, Class valueType, Object o) {
+ public MapEntryTypeValidator(Map<String, Object> params) {
+ this.keyType = (Class) params.get(ConfigValidationAnnotations.ValidatorParams.KEY_TYPE);
+ this.valueType = (Class) params.get(ConfigValidationAnnotations.ValidatorParams.VALUE_TYPE);
+ }
+
+ @Override
+ public void validateField(String name, Object o) {
+ validateField(name, this.keyType, this.valueType, o);
+ }
+
+ public static void validateField(String name, Class keyType, Class valueType, Object o) {
ConfigValidationUtils.NestableFieldValidator validator = ConfigValidationUtils.mapFv(keyType, valueType, false);
validator.validateField(name, o);
}
@@ -312,15 +344,27 @@ public class ConfigValidation {
/**
* validates each key and each value against the respective arrays of validators
*/
- public static class MapEntryCustomValidator {
+ public static class MapEntryCustomValidator extends Validator{
+
+ private Class[] keyValidators;
+ private Class[] valueValidators;
+
+ public MapEntryCustomValidator(Map<String, Object> params) {
+ this.keyValidators = (Class []) params.get(ConfigValidationAnnotations.ValidatorParams.KEY_VALIDATOR_CLASSES);
+ this.valueValidators = (Class []) params.get(ConfigValidationAnnotations.ValidatorParams.VALUE_VALIDATOR_CLASSES);
+ }
- public void validateField(String name, Class[] keyValidators, Class[] valueValidators, Object o) throws IllegalAccessException, InstantiationException {
+ @Override
+ public void validateField(String name, Object o) throws InstantiationException, IllegalAccessException {
+ validateField(name, this.keyValidators, this.valueValidators, o);
+ }
+
+ public static void validateField(String name, Class[] keyValidators, Class[] valueValidators, Object o) throws IllegalAccessException, InstantiationException {
if (o == null) {
return;
}
//check if Map
- SimpleTypeValidator isMap = new SimpleTypeValidator();
- isMap.validateField(name, Map.class, o);
+ SimpleTypeValidator.validateField(name, Map.class, o);
for (Map.Entry<Object, Object> entry : ((Map<Object, Object>) o).entrySet()) {
for (Class kv : keyValidators) {
Object keyValidator = kv.newInstance();
@@ -347,12 +391,22 @@ public class ConfigValidation {
*/
public static class PositiveNumberValidator extends Validator{
+ private boolean includeZero;
+
+ public PositiveNumberValidator() {
+ this.includeZero = false;
+ }
+
+ public PositiveNumberValidator(Map<String, Object> params) {
+ this.includeZero = (boolean) params.get(ConfigValidationAnnotations.ValidatorParams.INCLUDE_ZERO);
+ }
+
@Override
public void validateField(String name, Object o) {
- validateField(name, false, o);
+ validateField(name, this.includeZero, o);
}
- public void validateField(String name, boolean includeZero, Object o) {
+ public static void validateField(String name, boolean includeZero, Object o) {
if (o == null) {
return;
}
@@ -409,6 +463,7 @@ public class ConfigValidation {
if (annotations.length == 0) {
LOG.warn("Field {} does not have validator annotation", field);
}
+
for (Annotation annotation : annotations) {
String type = annotation.annotationType().getName();
Class validatorClass = null;
@@ -424,62 +479,20 @@ public class ConfigValidation {
Object v = validatorClass.cast(annotation);
String key = (String) field.get(null);
Class clazz = (Class) validatorClass
- .getMethod(ConfigValidationAnnotations.VALIDATOR_CLASS).invoke(v);
- //Determining which method from which class should be invoked based on what fields/parameters the annotation has
- if (hasMethod(validatorClass, ConfigValidationAnnotations.TYPE)) {
-
- TypeValidator o = ((Class<TypeValidator>) clazz).newInstance();
-
- Class objectType = (Class) validatorClass.getMethod(ConfigValidationAnnotations.TYPE).invoke(v);
-
- o.validateField(field.getName(), objectType, conf.get(key));
-
- } else if (hasMethod(validatorClass, ConfigValidationAnnotations.ENTRY_VALIDATOR_CLASSES)) {
-
- ListEntryCustomValidator o = ((Class<ListEntryCustomValidator>) clazz).newInstance();
-
- Class[] entryValidators = (Class[]) validatorClass.getMethod(ConfigValidationAnnotations.ENTRY_VALIDATOR_CLASSES).invoke(v);
-
- o.validateField(field.getName(), entryValidators, conf.get(key));
-
- } else if (hasMethod(validatorClass, ConfigValidationAnnotations.KEY_VALIDATOR_CLASSES)
- && hasMethod(validatorClass, ConfigValidationAnnotations.VALUE_VALIDATOR_CLASSES)) {
-
- MapEntryCustomValidator o = ((Class<MapEntryCustomValidator>) clazz).newInstance();
-
- Class[] keyValidators = (Class[]) validatorClass.getMethod(ConfigValidationAnnotations.KEY_VALIDATOR_CLASSES).invoke(v);
-
- Class[] valueValidators = (Class[]) validatorClass.getMethod(ConfigValidationAnnotations.VALUE_VALIDATOR_CLASSES).invoke(v);
-
- o.validateField(field.getName(), keyValidators, valueValidators, conf.get(key));
-
- } else if (hasMethod(validatorClass, ConfigValidationAnnotations.KEY_TYPE)
- && hasMethod(validatorClass, ConfigValidationAnnotations.VALUE_TYPE)) {
-
- MapEntryTypeValidator o = ((Class<MapEntryTypeValidator>) clazz).newInstance();
-
- Class keyType = (Class) validatorClass.getMethod(ConfigValidationAnnotations.KEY_TYPE).invoke(v);
-
- Class valueType = (Class) validatorClass.getMethod(ConfigValidationAnnotations.VALUE_TYPE).invoke(v);
-
- o.validateField(field.getName(), keyType, valueType, conf.get(key));
-
- } else if (hasMethod(validatorClass, ConfigValidationAnnotations.INCLUDE_ZERO)) {
-
- PositiveNumberValidator o = ((Class<PositiveNumberValidator>) clazz).newInstance();
-
- Boolean includeZero = (Boolean) validatorClass.getMethod(ConfigValidationAnnotations.INCLUDE_ZERO).invoke(v);
-
- o.validateField(field.getName(), includeZero, conf.get(key));
-
+ .getMethod(ConfigValidationAnnotations.ValidatorParams.VALIDATOR_CLASS).invoke(v);
+ Validator o = null;
+ Map<String, Object> params = getParamsFromAnnotation(validatorClass, v);
+ //two constructor signatures used to initialize validators.
+ //One constructor takes input a Map of arguments, the other doesn't take any arguments (default constructor)
+ //If validator has a constructor that takes a Map as an argument call that constructor
+ if(hasConstructor(clazz, Map.class)) {
+ o = (Validator) clazz.getConstructor(Map.class).newInstance(params);
}
- //For annotations that does not have any additional fields. Call corresponding validateField method
+ //If not call default constructor
else {
-
- ConfigValidation.Validator o = ((Class<ConfigValidation.Validator>) clazz).newInstance();
-
- o.validateField(field.getName(), conf.get(key));
+ o = (((Class<Validator>) clazz).newInstance());
}
+ o.validateField(field.getName(), conf.get(key));
}
}
}
@@ -512,6 +525,33 @@ public class ConfigValidation {
}
}
+ private static Map<String,Object> getParamsFromAnnotation(Class validatorClass, Object v) throws InvocationTargetException, IllegalAccessException {
+ Map<String, Object> params = new HashMap<String, Object>();
+ for(Method method : validatorClass.getDeclaredMethods()) {
+
+ Object value = null;
+ try {
+ value = (Object) method.invoke(v);
+ } catch (IllegalArgumentException ex) {
+ value = null;
+ }
+ if(value != null) {
+ params.put(method.getName(), value);
+ }
+ }
+ return params;
+ }
+
+ private static boolean hasConstructor(Class clazz, Class paramClass) {
+ Class[] classes = {paramClass};
+ try {
+ clazz.getConstructor(classes);
+ } catch (NoSuchMethodException e) {
+ return false;
+ }
+ return true;
+ }
+
private static boolean hasMethod(Class clazz, String method) {
try {
clazz.getMethod(method);
http://git-wip-us.apache.org/repos/asf/storm/blob/b5cb2ecd/storm-core/src/jvm/backtype/storm/validation/ConfigValidationAnnotations.java
----------------------------------------------------------------------
diff --git a/storm-core/src/jvm/backtype/storm/validation/ConfigValidationAnnotations.java b/storm-core/src/jvm/backtype/storm/validation/ConfigValidationAnnotations.java
index be3b665..0b64479 100644
--- a/storm-core/src/jvm/backtype/storm/validation/ConfigValidationAnnotations.java
+++ b/storm-core/src/jvm/backtype/storm/validation/ConfigValidationAnnotations.java
@@ -29,21 +29,23 @@ import java.lang.annotation.RetentionPolicy;
* For every annotation there must validator class to do the validation
* To add another annotation for config validation, add another annotation @interface class. Implement the corresponding
* validator logic in a class in ConfigValidation. Make sure validateField method in ConfigValidation knows how to use the validator
- * and which method definition/parameters to pass in based on what fields are in the annotation.
+ * and which method definition/parameters to pass in based on what fields are in the annotation. By default, params of annotations
+ * will be passed into a constructor that takes a Map as a parameter.
*/
public class ConfigValidationAnnotations {
/**
* Field names for annotations
*/
-
- static final String VALIDATOR_CLASS = "validatorClass";
- static final String TYPE = "type";
- static final String ENTRY_VALIDATOR_CLASSES = "entryValidatorClasses";
- static final String KEY_VALIDATOR_CLASSES = "keyValidatorClasses";
- static final String VALUE_VALIDATOR_CLASSES = "valueValidatorClasses";
- static final String KEY_TYPE = "keyType";
- static final String VALUE_TYPE = "valueType";
- static final String INCLUDE_ZERO = "includeZero";
+ public static class ValidatorParams {
+ static final String VALIDATOR_CLASS = "validatorClass";
+ static final String TYPE = "type";
+ static final String ENTRY_VALIDATOR_CLASSES = "entryValidatorClasses";
+ static final String KEY_VALIDATOR_CLASSES = "keyValidatorClasses";
+ static final String VALUE_VALIDATOR_CLASSES = "valueValidatorClasses";
+ static final String KEY_TYPE = "keyType";
+ static final String VALUE_TYPE = "valueType";
+ static final String INCLUDE_ZERO = "includeZero";
+ }
/**
* Validators with fields: validatorClass and type
http://git-wip-us.apache.org/repos/asf/storm/blob/b5cb2ecd/storm-core/test/jvm/backtype/storm/TestConfigValidate.java
----------------------------------------------------------------------
diff --git a/storm-core/test/jvm/backtype/storm/TestConfigValidate.java b/storm-core/test/jvm/backtype/storm/TestConfigValidate.java
index 09d2be9..3ac1d47 100644
--- a/storm-core/test/jvm/backtype/storm/TestConfigValidate.java
+++ b/storm-core/test/jvm/backtype/storm/TestConfigValidate.java
@@ -328,7 +328,6 @@ public class TestConfigValidate {
@Test
public void testListEntryTypeValidator() {
- ListEntryTypeValidator validator = new ListEntryTypeValidator();
Collection<Object> testCases1 = new LinkedList<Object>();
Collection<Object> testCases2 = new LinkedList<Object>();
Collection<Object> testCases3 = new LinkedList<Object>();
@@ -340,12 +339,12 @@ public class TestConfigValidate {
testCases1.add(Arrays.asList(testCase2));
for (Object value : testCases1) {
- validator.validateField("test", String.class, value);
+ ListEntryTypeValidator.validateField("test", String.class, value);
}
for (Object value : testCases1) {
try {
- validator.validateField("test", Number.class, value);
+ ListEntryTypeValidator.validateField("test", Number.class, value);
Assert.fail("Expected Exception not Thrown for value: " + value);
} catch (IllegalArgumentException Ex) {
}
@@ -359,13 +358,13 @@ public class TestConfigValidate {
testCases2.add(Arrays.asList(testCase5));
for (Object value : testCases2) {
try {
- validator.validateField("test", String.class, value);
+ ListEntryTypeValidator.validateField("test", String.class, value);
Assert.fail("Expected Exception not Thrown for value: " + value);
} catch (IllegalArgumentException Ex) {
}
}
for (Object value : testCases2) {
- validator.validateField("test", Number.class, value);
+ ListEntryTypeValidator.validateField("test", Number.class, value);
}
Object[] testCase6 = {1000, 0, 1000, "5"};
@@ -374,14 +373,14 @@ public class TestConfigValidate {
testCases3.add(Arrays.asList(testCase7));
for (Object value : testCases3) {
try {
- validator.validateField("test", String.class, value);
+ ListEntryTypeValidator.validateField("test", String.class, value);
Assert.fail("Expected Exception not Thrown for value: " + value);
} catch (IllegalArgumentException Ex) {
}
}
for (Object value : testCases1) {
try {
- validator.validateField("test", Number.class, value);
+ ListEntryTypeValidator.validateField("test", Number.class, value);
Assert.fail("Expected Exception not Thrown for value: " + value);
} catch (IllegalArgumentException Ex) {
}