You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sqoop.apache.org by ab...@apache.org on 2014/10/10 05:06:55 UTC

[03/50] [abbrv] git commit: SQOOP-1468: Sqoop2: Validations: Introduce advanced validators that can be parametrized

SQOOP-1468: Sqoop2: Validations: Introduce advanced validators that can be parametrized


Project: http://git-wip-us.apache.org/repos/asf/sqoop/repo
Commit: http://git-wip-us.apache.org/repos/asf/sqoop/commit/e71dd757
Tree: http://git-wip-us.apache.org/repos/asf/sqoop/tree/e71dd757
Diff: http://git-wip-us.apache.org/repos/asf/sqoop/diff/e71dd757

Branch: refs/heads/sqoop2
Commit: e71dd75793982b1d6e5109b8ef2209c835a79b68
Parents: c0b22b1
Author: Jarek Jarcec Cecho <ja...@apache.org>
Authored: Wed Sep 3 11:17:48 2014 -0700
Committer: Abraham Elmahrek <ab...@elmahrek.com>
Committed: Thu Oct 9 17:58:17 2014 -0700

----------------------------------------------------------------------
 .../apache/sqoop/model/ConfigurationClass.java  |   4 +-
 .../java/org/apache/sqoop/model/FormClass.java  |   4 +-
 .../main/java/org/apache/sqoop/model/Input.java |   4 +-
 .../java/org/apache/sqoop/model/Validator.java  |  45 ++++++++
 .../sqoop/validation/ValidationResult.java      |   4 +-
 .../sqoop/validation/ValidationRunner.java      |  18 ++--
 .../validators/AbstractValidator.java           | 103 +++++++++++++++++++
 .../validation/validators/ClassAvailable.java   |   2 +-
 .../sqoop/validation/validators/Contains.java   |  32 ++++++
 .../sqoop/validation/validators/NotEmpty.java   |   2 +-
 .../sqoop/validation/validators/NotNull.java    |   2 +-
 .../sqoop/validation/validators/StartsWith.java |  32 ++++++
 .../sqoop/validation/validators/Validator.java  |  80 --------------
 .../sqoop/validation/TestValidationRunner.java  |  42 ++++++--
 .../validators/TestClassAvailable.java          |   2 +-
 .../validation/validators/TestContains.java     |  90 ++++++++++++++++
 .../validation/validators/TestNotEmpty.java     |   2 +-
 .../validation/validators/TestNotNull.java      |   2 +-
 .../validation/validators/TestStartsWith.java   |  74 +++++++++++++
 .../validation/validators/TestValidator.java    |   2 +-
 .../jdbc/configuration/ConnectionForm.java      |  12 ++-
 .../jdbc/configuration/FromTableForm.java       |  19 ++--
 .../jdbc/configuration/ToTableForm.java         |   7 +-
 23 files changed, 450 insertions(+), 134 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/sqoop/blob/e71dd757/common/src/main/java/org/apache/sqoop/model/ConfigurationClass.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/model/ConfigurationClass.java b/common/src/main/java/org/apache/sqoop/model/ConfigurationClass.java
index 5323bd9..73374d8 100644
--- a/common/src/main/java/org/apache/sqoop/model/ConfigurationClass.java
+++ b/common/src/main/java/org/apache/sqoop/model/ConfigurationClass.java
@@ -17,8 +17,6 @@
  */
 package org.apache.sqoop.model;
 
-import org.apache.sqoop.validation.validators.Validator;
-
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -37,5 +35,5 @@ public @interface ConfigurationClass {
    *
    * @return
    */
-  Class<? extends Validator>[] validators() default {};
+  Validator[] validators() default {};
 }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/e71dd757/common/src/main/java/org/apache/sqoop/model/FormClass.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/model/FormClass.java b/common/src/main/java/org/apache/sqoop/model/FormClass.java
index 48bff3c..6048d03 100644
--- a/common/src/main/java/org/apache/sqoop/model/FormClass.java
+++ b/common/src/main/java/org/apache/sqoop/model/FormClass.java
@@ -17,8 +17,6 @@
  */
 package org.apache.sqoop.model;
 
-import org.apache.sqoop.validation.validators.Validator;
-
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -43,5 +41,5 @@ public @interface FormClass {
    *
    * @return
    */
-  Class<? extends Validator>[] validators() default {};
+  Validator[] validators() default {};
 }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/e71dd757/common/src/main/java/org/apache/sqoop/model/Input.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/model/Input.java b/common/src/main/java/org/apache/sqoop/model/Input.java
index 61fc01a..2b32e43 100644
--- a/common/src/main/java/org/apache/sqoop/model/Input.java
+++ b/common/src/main/java/org/apache/sqoop/model/Input.java
@@ -17,8 +17,6 @@
  */
 package org.apache.sqoop.model;
 
-import org.apache.sqoop.validation.validators.Validator;
-
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -51,5 +49,5 @@ public @interface Input {
    *
    * @return
    */
-  Class<? extends Validator>[] validators() default {};
+  Validator[] validators() default {};
 }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/e71dd757/common/src/main/java/org/apache/sqoop/model/Validator.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/model/Validator.java b/common/src/main/java/org/apache/sqoop/model/Validator.java
new file mode 100644
index 0000000..6368a9d
--- /dev/null
+++ b/common/src/main/java/org/apache/sqoop/model/Validator.java
@@ -0,0 +1,45 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sqoop.model;
+
+import org.apache.sqoop.validation.validators.AbstractValidator;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Annotation for specifying validators
+ *
+ * Usage without any parameters:
+ * @Validator(ClassName.class)
+ *
+ * To specify string parameter call:
+ * @Validator(value = ClassName.class, strArg = "Hello World!")
+ */
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Validator {
+  /**
+   * Validator implementation that should be executed.
+   */
+  Class<? extends AbstractValidator> value();
+
+  /**
+   * Optional argument that should be given to the validator before execution.
+   */
+  String strArg() default AbstractValidator.DEFAULT_STRING_ARGUMENT;
+}

http://git-wip-us.apache.org/repos/asf/sqoop/blob/e71dd757/common/src/main/java/org/apache/sqoop/validation/ValidationResult.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/validation/ValidationResult.java b/common/src/main/java/org/apache/sqoop/validation/ValidationResult.java
index 2782fac..ae8f1d1 100644
--- a/common/src/main/java/org/apache/sqoop/validation/ValidationResult.java
+++ b/common/src/main/java/org/apache/sqoop/validation/ValidationResult.java
@@ -17,7 +17,7 @@
  */
 package org.apache.sqoop.validation;
 
-import org.apache.sqoop.validation.validators.Validator;
+import org.apache.sqoop.validation.validators.AbstractValidator;
 
 import java.util.HashMap;
 import java.util.List;
@@ -49,7 +49,7 @@ public class ValidationResult {
    * @param name Full name of the validated object
    * @param validator Executed validator
    */
-  public void addValidator(String name, Validator validator) {
+  public void addValidator(String name, AbstractValidator validator) {
     if(validator.getStatus() == Status.getDefault()) {
       return;
     }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/e71dd757/common/src/main/java/org/apache/sqoop/validation/ValidationRunner.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/validation/ValidationRunner.java b/common/src/main/java/org/apache/sqoop/validation/ValidationRunner.java
index 46e2d56..f36faf2 100644
--- a/common/src/main/java/org/apache/sqoop/validation/ValidationRunner.java
+++ b/common/src/main/java/org/apache/sqoop/validation/ValidationRunner.java
@@ -22,8 +22,9 @@ import org.apache.sqoop.model.Form;
 import org.apache.sqoop.model.FormClass;
 import org.apache.sqoop.model.FormUtils;
 import org.apache.sqoop.model.Input;
+import org.apache.sqoop.model.Validator;
 import org.apache.sqoop.utils.ClassUtils;
-import org.apache.sqoop.validation.validators.Validator;
+import org.apache.sqoop.validation.validators.AbstractValidator;
 
 import java.lang.reflect.Field;
 
@@ -114,14 +115,14 @@ public class ValidationRunner {
    *
    * @param name Full name of the object
    * @param object Input, Form or Class instance
-   * @param classes Validators array
+   * @param validators Validators array
    * @return
    */
-  private ValidationResult validateArray(String name, Object object, Class<? extends Validator> []classes) {
+  private ValidationResult validateArray(String name, Object object, Validator[] validators) {
     ValidationResult result = new ValidationResult();
 
-    for (Class<? extends Validator> klass : classes) {
-      Validator v = executeValidator(object, klass);
+    for (Validator validator : validators) {
+      AbstractValidator v = executeValidator(object, validator);
       result.addValidator(name, v);
     }
 
@@ -132,11 +133,12 @@ public class ValidationRunner {
    * Execute single validator.
    *
    * @param object Input, Form or Class instance
-   * @param klass Validator's clas
+   * @param validator Validator annotation
    * @return
    */
-  private Validator executeValidator(Object object, Class<? extends Validator> klass) {
-    Validator instance = (Validator) ClassUtils.instantiate(klass);
+  private AbstractValidator executeValidator(Object object, Validator validator) {
+    AbstractValidator instance = (AbstractValidator) ClassUtils.instantiate(validator.value());
+    instance.setStringArgument(validator.strArg());
     instance.validate(object);
     return instance;
   }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/e71dd757/common/src/main/java/org/apache/sqoop/validation/validators/AbstractValidator.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/validation/validators/AbstractValidator.java b/common/src/main/java/org/apache/sqoop/validation/validators/AbstractValidator.java
new file mode 100644
index 0000000..9dbb44c
--- /dev/null
+++ b/common/src/main/java/org/apache/sqoop/validation/validators/AbstractValidator.java
@@ -0,0 +1,103 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sqoop.validation.validators;
+
+import org.apache.sqoop.validation.Message;
+import org.apache.sqoop.validation.Status;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Abstract validator class.
+ *
+ * Can be used to validate inputs, forms and configuration classes.
+ */
+abstract public class AbstractValidator<T> {
+
+  /**
+   * Default value of String argument.
+   */
+  public static final String DEFAULT_STRING_ARGUMENT = "";
+
+  /**
+   * Validation check.
+   *
+   * To be implemented by our children.
+   *
+   * @param instance Object to validate (depending on what we are validating)
+   */
+  abstract public void validate(T instance);
+
+  /**
+   * Messages generated during validation.
+   */
+  private List<Message> messages;
+
+  /**
+   * Overall status of the validation.
+   */
+  private Status status;
+
+  /**
+   * Optional String argument that can be defined for the Validator
+   */
+  private String stringArgument;
+
+  public AbstractValidator() {
+    reset();
+  }
+
+  protected void addMessage(Message msg) {
+    status = Status.getWorstStatus(status, msg.getStatus());
+    messages.add(msg);
+  }
+
+  protected void addMessage(Status status, String msg) {
+    addMessage(new Message(status, msg));
+  }
+
+  public List<Message> getMessages() {
+    return messages;
+  }
+
+  public Status getStatus() {
+    return status;
+  }
+
+  public void setStringArgument(String arg) {
+    this.stringArgument = arg;
+  }
+
+  public String getStringArgument() {
+    return stringArgument;
+  }
+
+  /**
+   * Reset validator state.
+   *
+   * * Previous messages
+   * * Status
+   * * Any stored arguments
+   */
+  public void reset() {
+    messages = new LinkedList<Message>();
+    status = Status.getDefault();
+    stringArgument = DEFAULT_STRING_ARGUMENT;
+  }
+}

http://git-wip-us.apache.org/repos/asf/sqoop/blob/e71dd757/common/src/main/java/org/apache/sqoop/validation/validators/ClassAvailable.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/validation/validators/ClassAvailable.java b/common/src/main/java/org/apache/sqoop/validation/validators/ClassAvailable.java
index 2adfe6c..52a8fdd 100644
--- a/common/src/main/java/org/apache/sqoop/validation/validators/ClassAvailable.java
+++ b/common/src/main/java/org/apache/sqoop/validation/validators/ClassAvailable.java
@@ -23,7 +23,7 @@ import org.apache.sqoop.validation.Status;
 /**
  * Ensure that given String Input is a class that is available to this JVM.
  */
-public class ClassAvailable extends Validator<String> {
+public class ClassAvailable extends AbstractValidator<String> {
   @Override
   public void validate(String klass) {
     try {

http://git-wip-us.apache.org/repos/asf/sqoop/blob/e71dd757/common/src/main/java/org/apache/sqoop/validation/validators/Contains.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/validation/validators/Contains.java b/common/src/main/java/org/apache/sqoop/validation/validators/Contains.java
new file mode 100644
index 0000000..8920c72
--- /dev/null
+++ b/common/src/main/java/org/apache/sqoop/validation/validators/Contains.java
@@ -0,0 +1,32 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sqoop.validation.validators;
+
+import org.apache.sqoop.validation.Status;
+
+/**
+ * String validator to verify presence of a sub string (provided as a String argument)
+ */
+public class Contains extends AbstractValidator<String> {
+  @Override
+  public void validate(String str) {
+    if(str == null || !str.contains(getStringArgument())) {
+      addMessage(Status.UNACCEPTABLE, "String must contain substring: " + getStringArgument());
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/sqoop/blob/e71dd757/common/src/main/java/org/apache/sqoop/validation/validators/NotEmpty.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/validation/validators/NotEmpty.java b/common/src/main/java/org/apache/sqoop/validation/validators/NotEmpty.java
index 520beea..248a2fa 100644
--- a/common/src/main/java/org/apache/sqoop/validation/validators/NotEmpty.java
+++ b/common/src/main/java/org/apache/sqoop/validation/validators/NotEmpty.java
@@ -24,7 +24,7 @@ import org.apache.sqoop.validation.Status;
  *
  * Will also ensure that the string is not null.
  */
-public class NotEmpty extends Validator<String> {
+public class NotEmpty extends AbstractValidator<String> {
   @Override
   public void validate(String instance) {
     if (instance == null || instance.isEmpty()) {

http://git-wip-us.apache.org/repos/asf/sqoop/blob/e71dd757/common/src/main/java/org/apache/sqoop/validation/validators/NotNull.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/validation/validators/NotNull.java b/common/src/main/java/org/apache/sqoop/validation/validators/NotNull.java
index fb8a926..93b5fa7 100644
--- a/common/src/main/java/org/apache/sqoop/validation/validators/NotNull.java
+++ b/common/src/main/java/org/apache/sqoop/validation/validators/NotNull.java
@@ -22,7 +22,7 @@ import org.apache.sqoop.validation.Status;
 /**
  * Ensure that given object is never null.
  */
-public class NotNull<T> extends Validator<T> {
+public class NotNull<T> extends AbstractValidator<T> {
   @Override
   public void validate(T instance) {
     if (instance == null) {

http://git-wip-us.apache.org/repos/asf/sqoop/blob/e71dd757/common/src/main/java/org/apache/sqoop/validation/validators/StartsWith.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/validation/validators/StartsWith.java b/common/src/main/java/org/apache/sqoop/validation/validators/StartsWith.java
new file mode 100644
index 0000000..808e1f7
--- /dev/null
+++ b/common/src/main/java/org/apache/sqoop/validation/validators/StartsWith.java
@@ -0,0 +1,32 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sqoop.validation.validators;
+
+import org.apache.sqoop.validation.Status;
+
+/**
+ * String validator to verify if Input starts with given string (String argument).
+ */
+public class StartsWith extends AbstractValidator<String> {
+  @Override
+  public void validate(String str) {
+    if(str == null || !str.startsWith(getStringArgument())) {
+      addMessage(Status.UNACCEPTABLE, "String must start with: " + getStringArgument());
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/sqoop/blob/e71dd757/common/src/main/java/org/apache/sqoop/validation/validators/Validator.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/validation/validators/Validator.java b/common/src/main/java/org/apache/sqoop/validation/validators/Validator.java
deleted file mode 100644
index bdb7c20..0000000
--- a/common/src/main/java/org/apache/sqoop/validation/validators/Validator.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.sqoop.validation.validators;
-
-import org.apache.sqoop.validation.Message;
-import org.apache.sqoop.validation.Status;
-
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * Abstract validator class.
- *
- * Can be used to validate inputs, forms and configuration classes.
- */
-abstract public class Validator<T> {
-
-  /**
-   * Validation check.
-   *
-   * To be implemented by our children.
-   *
-   * @param instance Object to validate (depending on what we are validating)
-   */
-  abstract public void validate(T instance);
-
-  /**
-   * Messages generated during validation.
-   */
-  private List<Message> messages;
-
-  /**
-   * Overall status of the validation.
-   */
-  private Status status;
-
-  public Validator() {
-    reset();
-  }
-
-  protected void addMessage(Message msg) {
-    status = Status.getWorstStatus(status, msg.getStatus());
-    messages.add(msg);
-  }
-
-  protected void addMessage(Status status, String msg) {
-    addMessage(new Message(status, msg));
-  }
-
-  public List<Message> getMessages() {
-    return messages;
-  }
-
-  public Status getStatus() {
-    return status;
-  }
-
-  /**
-   * Reset validator state (all previous messages).
-   */
-  public void reset() {
-    messages = new LinkedList<Message>();
-    status = Status.getDefault();
-  }
-}

http://git-wip-us.apache.org/repos/asf/sqoop/blob/e71dd757/common/src/test/java/org/apache/sqoop/validation/TestValidationRunner.java
----------------------------------------------------------------------
diff --git a/common/src/test/java/org/apache/sqoop/validation/TestValidationRunner.java b/common/src/test/java/org/apache/sqoop/validation/TestValidationRunner.java
index 1961425..647abe0 100644
--- a/common/src/test/java/org/apache/sqoop/validation/TestValidationRunner.java
+++ b/common/src/test/java/org/apache/sqoop/validation/TestValidationRunner.java
@@ -21,9 +21,11 @@ import org.apache.sqoop.model.ConfigurationClass;
 import org.apache.sqoop.model.Form;
 import org.apache.sqoop.model.FormClass;
 import org.apache.sqoop.model.Input;
+import org.apache.sqoop.model.Validator;
+import org.apache.sqoop.validation.validators.Contains;
 import org.apache.sqoop.validation.validators.NotEmpty;
 import org.apache.sqoop.validation.validators.NotNull;
-import org.apache.sqoop.validation.validators.Validator;
+import org.apache.sqoop.validation.validators.AbstractValidator;
 import org.junit.Test;
 
 import static org.junit.Assert.assertEquals;
@@ -33,12 +35,12 @@ import static org.junit.Assert.assertTrue;
  */
 public class TestValidationRunner {
 
-  @FormClass(validators = {FormA.FormValidator.class})
+  @FormClass(validators = {@Validator(FormA.FormValidator.class)})
   public static class FormA {
-    @Input(validators = {NotNull.class})
+    @Input(validators = {@Validator(NotNull.class)})
     String notNull;
 
-    public static class FormValidator extends Validator<FormA> {
+    public static class FormValidator extends AbstractValidator<FormA> {
       @Override
       public void validate(FormA form) {
         if(form.notNull == null) {
@@ -80,7 +82,13 @@ public class TestValidationRunner {
 
   @FormClass
   public static class FormB {
-    @Input(validators = {NotNull.class, NotEmpty.class})
+    @Input(validators = {@Validator(NotNull.class), @Validator(NotEmpty.class)})
+    String str;
+  }
+
+  @FormClass
+  public static class FormC {
+    @Input(validators = {@Validator(value = Contains.class, strArg = "findme")})
     String str;
   }
 
@@ -98,14 +106,34 @@ public class TestValidationRunner {
     assertEquals(2, result.getMessages().get("formName.str").size());
   }
 
-  @ConfigurationClass(validators = {ConfigurationA.ClassValidator.class})
+  @Test
+  public void testValidatorWithParameters() {
+    FormC form = new FormC();
+    ValidationRunner runner = new ValidationRunner();
+    ValidationResult result;
+
+    // Sub string not found
+    form.str = "Mordor";
+    result = runner.validateForm("formName", form);
+    assertEquals(Status.UNACCEPTABLE, result.getStatus());
+    assertEquals(1, result.getMessages().size());
+    assertTrue(result.getMessages().containsKey("formName.str"));
+
+    // Sub string found
+    form.str = "Morfindmedor";
+    result = runner.validateForm("formName", form);
+    assertEquals(Status.FINE, result.getStatus());
+    assertEquals(0, result.getMessages().size());
+  }
+
+  @ConfigurationClass(validators = {@Validator(ConfigurationA.ClassValidator.class)})
   public static class ConfigurationA {
     @Form FormA formA;
     public ConfigurationA() {
       formA = new FormA();
     }
 
-    public static class ClassValidator extends Validator<ConfigurationA> {
+    public static class ClassValidator extends AbstractValidator<ConfigurationA> {
       @Override
       public void validate(ConfigurationA conf) {
         if("error".equals(conf.formA.notNull)) {

http://git-wip-us.apache.org/repos/asf/sqoop/blob/e71dd757/common/src/test/java/org/apache/sqoop/validation/validators/TestClassAvailable.java
----------------------------------------------------------------------
diff --git a/common/src/test/java/org/apache/sqoop/validation/validators/TestClassAvailable.java b/common/src/test/java/org/apache/sqoop/validation/validators/TestClassAvailable.java
index 511b3b4..62b2e0a 100644
--- a/common/src/test/java/org/apache/sqoop/validation/validators/TestClassAvailable.java
+++ b/common/src/test/java/org/apache/sqoop/validation/validators/TestClassAvailable.java
@@ -29,7 +29,7 @@ import static org.junit.Assert.assertEquals;
  */
 public class TestClassAvailable {
 
-  Validator validator = new ClassAvailable();
+  AbstractValidator validator = new ClassAvailable();
 
   @Test
   public void test() {

http://git-wip-us.apache.org/repos/asf/sqoop/blob/e71dd757/common/src/test/java/org/apache/sqoop/validation/validators/TestContains.java
----------------------------------------------------------------------
diff --git a/common/src/test/java/org/apache/sqoop/validation/validators/TestContains.java b/common/src/test/java/org/apache/sqoop/validation/validators/TestContains.java
new file mode 100644
index 0000000..b5dce62
--- /dev/null
+++ b/common/src/test/java/org/apache/sqoop/validation/validators/TestContains.java
@@ -0,0 +1,90 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sqoop.validation.validators;
+
+import org.apache.sqoop.validation.Status;
+import org.junit.Test;
+
+import static junit.framework.Assert.assertEquals;
+
+/**
+ */
+public class TestContains {
+
+  AbstractValidator validator = new Contains();
+
+  @Test
+  public void test() {
+    assertEquals(0, validator.getMessages().size());
+
+    // Default, no string argument set
+    validator.validate("str");
+    assertEquals(Status.FINE, validator.getStatus());
+    assertEquals(0, validator.getMessages().size());
+
+    // Searched substring is entire string
+    validator.reset();
+    validator.setStringArgument("str");
+    validator.validate("str");
+    assertEquals(Status.FINE, validator.getStatus());
+    assertEquals(0, validator.getMessages().size());
+
+    // Just starts with
+    validator.reset();
+    validator.setStringArgument("str");
+    validator.validate("straaaaa");
+    assertEquals(Status.FINE, validator.getStatus());
+    assertEquals(0, validator.getMessages().size());
+
+    // Ends with
+    validator.reset();
+    validator.setStringArgument("str");
+    validator.validate("aaastr");
+    assertEquals(Status.FINE, validator.getStatus());
+    assertEquals(0, validator.getMessages().size());
+
+    // In the middle
+    validator.reset();
+    validator.setStringArgument("str");
+    validator.validate("aaastraaa");
+    assertEquals(Status.FINE, validator.getStatus());
+    assertEquals(0, validator.getMessages().size());
+
+    // Null string
+    validator.reset();
+    validator.setStringArgument("str");
+    validator.validate(null);
+    assertEquals(Status.UNACCEPTABLE, validator.getStatus());
+    assertEquals(1, validator.getMessages().size());
+
+    // Empty string
+    validator.reset();
+    validator.setStringArgument("str");
+    validator.validate("");
+    assertEquals(Status.UNACCEPTABLE, validator.getStatus());
+    assertEquals(1, validator.getMessages().size());
+
+    // "Random" string
+    validator.reset();
+    validator.setStringArgument("str");
+    validator.validate("Ahoj tady je meduza");
+    assertEquals(Status.UNACCEPTABLE, validator.getStatus());
+    assertEquals(1, validator.getMessages().size());
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/sqoop/blob/e71dd757/common/src/test/java/org/apache/sqoop/validation/validators/TestNotEmpty.java
----------------------------------------------------------------------
diff --git a/common/src/test/java/org/apache/sqoop/validation/validators/TestNotEmpty.java b/common/src/test/java/org/apache/sqoop/validation/validators/TestNotEmpty.java
index d225b06..5c9169a 100644
--- a/common/src/test/java/org/apache/sqoop/validation/validators/TestNotEmpty.java
+++ b/common/src/test/java/org/apache/sqoop/validation/validators/TestNotEmpty.java
@@ -29,7 +29,7 @@ import static org.junit.Assert.assertEquals;
  */
 public class TestNotEmpty {
 
-  Validator validator = new NotEmpty();
+  AbstractValidator validator = new NotEmpty();
 
   @Test
   public void test() {

http://git-wip-us.apache.org/repos/asf/sqoop/blob/e71dd757/common/src/test/java/org/apache/sqoop/validation/validators/TestNotNull.java
----------------------------------------------------------------------
diff --git a/common/src/test/java/org/apache/sqoop/validation/validators/TestNotNull.java b/common/src/test/java/org/apache/sqoop/validation/validators/TestNotNull.java
index 9c5bed5..91e5398 100644
--- a/common/src/test/java/org/apache/sqoop/validation/validators/TestNotNull.java
+++ b/common/src/test/java/org/apache/sqoop/validation/validators/TestNotNull.java
@@ -29,7 +29,7 @@ import static org.junit.Assert.assertEquals;
  */
 public class TestNotNull {
 
-  Validator validator = new NotNull();
+  AbstractValidator validator = new NotNull();
 
   @Test
   public void test() {

http://git-wip-us.apache.org/repos/asf/sqoop/blob/e71dd757/common/src/test/java/org/apache/sqoop/validation/validators/TestStartsWith.java
----------------------------------------------------------------------
diff --git a/common/src/test/java/org/apache/sqoop/validation/validators/TestStartsWith.java b/common/src/test/java/org/apache/sqoop/validation/validators/TestStartsWith.java
new file mode 100644
index 0000000..92409d9
--- /dev/null
+++ b/common/src/test/java/org/apache/sqoop/validation/validators/TestStartsWith.java
@@ -0,0 +1,74 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sqoop.validation.validators;
+
+import org.apache.sqoop.validation.Status;
+import org.junit.Test;
+
+import static junit.framework.Assert.assertEquals;
+
+/**
+ */
+public class TestStartsWith {
+
+  AbstractValidator validator = new StartsWith();
+
+  @Test
+  public void test() {
+    assertEquals(0, validator.getMessages().size());
+
+    // Default, no string argument set
+    validator.validate("str");
+    assertEquals(Status.FINE, validator.getStatus());
+    assertEquals(0, validator.getMessages().size());
+
+    // Searched substring is entire string
+    validator.validate("str");
+    assertEquals(Status.FINE, validator.getStatus());
+    assertEquals(0, validator.getMessages().size());
+
+    // Just starts with
+    validator.reset();
+    validator.setStringArgument("str");
+    validator.validate("strstr");
+    assertEquals(Status.FINE, validator.getStatus());
+    assertEquals(0, validator.getMessages().size());
+
+    // Null string
+    validator.reset();
+    validator.setStringArgument("str");
+    validator.validate(null);
+    assertEquals(Status.UNACCEPTABLE, validator.getStatus());
+    assertEquals(1, validator.getMessages().size());
+
+    // Empty string
+    validator.reset();
+    validator.setStringArgument("str");
+    validator.validate("");
+    assertEquals(Status.UNACCEPTABLE, validator.getStatus());
+    assertEquals(1, validator.getMessages().size());
+
+    // "Random" string
+    validator.reset();
+    validator.setStringArgument("str");
+    validator.validate("Ahoj tady je meduza");
+    assertEquals(Status.UNACCEPTABLE, validator.getStatus());
+    assertEquals(1, validator.getMessages().size());
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/sqoop/blob/e71dd757/common/src/test/java/org/apache/sqoop/validation/validators/TestValidator.java
----------------------------------------------------------------------
diff --git a/common/src/test/java/org/apache/sqoop/validation/validators/TestValidator.java b/common/src/test/java/org/apache/sqoop/validation/validators/TestValidator.java
index 1a5dbdd..3f60ee6 100644
--- a/common/src/test/java/org/apache/sqoop/validation/validators/TestValidator.java
+++ b/common/src/test/java/org/apache/sqoop/validation/validators/TestValidator.java
@@ -27,7 +27,7 @@ import static org.junit.Assert.assertEquals;
  *
  */
 public class TestValidator {
-  public static class ValidatorImpl extends Validator<String> {
+  public static class ValidatorImpl extends AbstractValidator<String> {
     @Override
     public void validate(String msg) {
       addMessage(Status.FINE, msg);

http://git-wip-us.apache.org/repos/asf/sqoop/blob/e71dd757/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/configuration/ConnectionForm.java
----------------------------------------------------------------------
diff --git a/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/configuration/ConnectionForm.java b/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/configuration/ConnectionForm.java
index e513770..3b5d70a 100644
--- a/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/configuration/ConnectionForm.java
+++ b/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/configuration/ConnectionForm.java
@@ -19,10 +19,12 @@ package org.apache.sqoop.connector.jdbc.configuration;
 
 import org.apache.sqoop.model.FormClass;
 import org.apache.sqoop.model.Input;
+import org.apache.sqoop.model.Validator;
 import org.apache.sqoop.validation.Status;
+import org.apache.sqoop.validation.validators.AbstractValidator;
 import org.apache.sqoop.validation.validators.NotEmpty;
-import org.apache.sqoop.validation.validators.Validator;
 import org.apache.sqoop.validation.validators.ClassAvailable;
+import org.apache.sqoop.validation.validators.StartsWith;
 
 import java.sql.DriverManager;
 import java.sql.SQLException;
@@ -31,12 +33,12 @@ import java.util.Map;
 /**
  *
  */
-@FormClass(validators = {ConnectionForm.FormValidator.class})
+@FormClass(validators = {@Validator(ConnectionForm.FormValidator.class)})
 public class ConnectionForm {
-  @Input(size = 128, validators = {NotEmpty.class, ClassAvailable.class} )
+  @Input(size = 128, validators = {@Validator(NotEmpty.class), @Validator(ClassAvailable.class)} )
   public String jdbcDriver;
 
-  @Input(size = 128, validators = {NotEmpty.class} )
+  @Input(size = 128, validators = {@Validator(value = StartsWith.class, strArg = "jdbc:")} )
   public String connectionString;
 
   @Input(size = 40)
@@ -48,7 +50,7 @@ public class ConnectionForm {
   @Input
   public Map<String, String> jdbcProperties;
 
-  public static class FormValidator extends Validator<ConnectionForm> {
+  public static class FormValidator extends AbstractValidator<ConnectionForm> {
     @Override
     public void validate(ConnectionForm form) {
       // See if we can connect to the database

http://git-wip-us.apache.org/repos/asf/sqoop/blob/e71dd757/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/configuration/FromTableForm.java
----------------------------------------------------------------------
diff --git a/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/configuration/FromTableForm.java b/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/configuration/FromTableForm.java
index 1c0b429..ac72546 100644
--- a/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/configuration/FromTableForm.java
+++ b/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/configuration/FromTableForm.java
@@ -20,13 +20,15 @@ package org.apache.sqoop.connector.jdbc.configuration;
 import org.apache.sqoop.connector.jdbc.GenericJdbcConnectorConstants;
 import org.apache.sqoop.model.FormClass;
 import org.apache.sqoop.model.Input;
+import org.apache.sqoop.model.Validator;
 import org.apache.sqoop.validation.Status;
-import org.apache.sqoop.validation.validators.Validator;
+import org.apache.sqoop.validation.validators.AbstractValidator;
+import org.apache.sqoop.validation.validators.Contains;
 
 /**
  *
  */
-@FormClass( validators = {FromTableForm.FormValidator.class})
+@FormClass( validators = {@Validator(FromTableForm.FormValidator.class)})
 public class FromTableForm {
   @Input(size = 50)
   public String schemaName;
@@ -34,7 +36,7 @@ public class FromTableForm {
   @Input(size = 50)
   public String tableName;
 
-  @Input(size = 2000, validators = {SqlConditionTokenValidator.class})
+  @Input(size = 2000, validators = {@Validator(value = Contains.class, strArg = GenericJdbcConnectorConstants.SQL_CONDITIONS_TOKEN)})
   public String sql;
 
   @Input(size = 50)
@@ -49,7 +51,7 @@ public class FromTableForm {
   @Input(size = 50)
   public String boundaryQuery;
 
-  public static class FormValidator extends Validator<FromTableForm> {
+  public static class FormValidator extends AbstractValidator<FromTableForm> {
     @Override
     public void validate(FromTableForm form) {
       if(form.tableName == null && form.sql == null) {
@@ -63,13 +65,4 @@ public class FromTableForm {
       }
     }
   }
-
-  public static class SqlConditionTokenValidator extends Validator<String> {
-    @Override
-    public void validate(String sql) {
-      if(sql != null && !sql.contains(GenericJdbcConnectorConstants.SQL_CONDITIONS_TOKEN)) {
-        addMessage(Status.UNACCEPTABLE, "SQL statement must contain placeholder for auto generated conditions - " + GenericJdbcConnectorConstants.SQL_CONDITIONS_TOKEN);
-      }
-    }
-  }
 }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/e71dd757/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/configuration/ToTableForm.java
----------------------------------------------------------------------
diff --git a/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/configuration/ToTableForm.java b/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/configuration/ToTableForm.java
index 0601a39..642da11 100644
--- a/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/configuration/ToTableForm.java
+++ b/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/configuration/ToTableForm.java
@@ -19,13 +19,14 @@ package org.apache.sqoop.connector.jdbc.configuration;
 
 import org.apache.sqoop.model.FormClass;
 import org.apache.sqoop.model.Input;
+import org.apache.sqoop.model.Validator;
 import org.apache.sqoop.validation.Status;
-import org.apache.sqoop.validation.validators.Validator;
+import org.apache.sqoop.validation.validators.AbstractValidator;
 
 /**
  *
  */
-@FormClass(validators = {ToTableForm.FormValidator.class})
+@FormClass(validators = {@Validator(ToTableForm.FormValidator.class)})
 public class ToTableForm {
   @Input(size = 50)   public String schemaName;
   @Input(size = 2000) public String tableName;
@@ -34,7 +35,7 @@ public class ToTableForm {
   @Input(size = 2000) public String stageTableName;
   @Input              public Boolean clearStageTable;
 
-  public static class FormValidator extends Validator<ToTableForm> {
+  public static class FormValidator extends AbstractValidator<ToTableForm> {
     @Override
     public void validate(ToTableForm form) {
       if(form.tableName == null && form.sql == null) {