Repository: sqoop
Updated Branches:
  refs/heads/SQOOP-1367 d8e336b3e -> 1a0e04ec4


Sqoop2: Validations: Provide Validation annotations


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

Branch: refs/heads/SQOOP-1367
Commit: 1a0e04ec4b252b5460bf5223b92c5f66c2a7dc35
Parents: d8e336b
Author: Abraham Elmahrek <[email protected]>
Authored: Mon Aug 18 10:44:37 2014 -0700
Committer: Abraham Elmahrek <[email protected]>
Committed: Mon Aug 18 10:44:37 2014 -0700

----------------------------------------------------------------------
 .../apache/sqoop/model/ConfigurationClass.java  | 11 ++++
 .../java/org/apache/sqoop/model/FormClass.java  | 12 ++++
 .../main/java/org/apache/sqoop/model/Input.java | 12 ++++
 .../org/apache/sqoop/validation/Message.java    | 68 +++++++++++++++++++
 .../org/apache/sqoop/validation/Status.java     |  8 ++-
 .../validation/validators/ClassAvailable.java   | 35 ++++++++++
 .../sqoop/validation/validators/NotEmpty.java   | 34 ++++++++++
 .../sqoop/validation/validators/NotNull.java    | 32 +++++++++
 .../sqoop/validation/validators/Validator.java  | 69 ++++++++++++++++++++
 .../validators/TestClassAvailable.java          | 50 ++++++++++++++
 .../validation/validators/TestNotEmpty.java     | 55 ++++++++++++++++
 .../validation/validators/TestNotNull.java      | 51 +++++++++++++++
 .../validation/validators/TestValidator.java    | 57 ++++++++++++++++
 .../jdbc/configuration/ConnectionForm.java      | 39 +++++++++--
 .../jdbc/configuration/FromTableForm.java       | 56 +++++++++++++---
 .../jdbc/configuration/ToTableForm.java         | 22 ++++++-
 16 files changed, 593 insertions(+), 18 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/sqoop/blob/1a0e04ec/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 5a28146..5323bd9 100644
--- a/common/src/main/java/org/apache/sqoop/model/ConfigurationClass.java
+++ b/common/src/main/java/org/apache/sqoop/model/ConfigurationClass.java
@@ -17,14 +17,25 @@
  */
 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;
+import java.lang.annotation.Target;
 
 /**
  * Class annotation. Each class that is used a configuration object where user
  * is expected to provide input need to have this annotation.
  */
 @Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
 public @interface ConfigurationClass {
 
+  /**
+   * List of validators associated with this Configuration class.
+   *
+   * @return
+   */
+  Class<? extends Validator>[] validators() default {};
 }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/1a0e04ec/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 d510ca0..48bff3c 100644
--- a/common/src/main/java/org/apache/sqoop/model/FormClass.java
+++ b/common/src/main/java/org/apache/sqoop/model/FormClass.java
@@ -17,13 +17,18 @@
  */
 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;
+import java.lang.annotation.Target;
 
 /**
  * Denote configuration class
  */
 @Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
 public @interface FormClass {
 
   /**
@@ -32,4 +37,11 @@ public @interface FormClass {
    * @return
    */
   short defaultSize() default -1;
+
+  /**
+   * List of validators associated with this form.
+   *
+   * @return
+   */
+  Class<? extends Validator>[] validators() default {};
 }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/1a0e04ec/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 6df2b9f..61fc01a 100644
--- a/common/src/main/java/org/apache/sqoop/model/Input.java
+++ b/common/src/main/java/org/apache/sqoop/model/Input.java
@@ -17,14 +17,19 @@
  */
 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;
+import java.lang.annotation.Target;
 
 /**
  * Field annotation. Each field that user might change in configuration object
  * need to have this annotation.
  */
 @Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
 public @interface Input {
   /**
    * Sqoop framework will ensure that sensitive information will not be easily
@@ -40,4 +45,11 @@ public @interface Input {
    * @return Maximal length
    */
   short size() default -1;
+
+  /**
+   * List of validators associated with this input.
+   *
+   * @return
+   */
+  Class<? extends Validator>[] validators() default {};
 }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/1a0e04ec/common/src/main/java/org/apache/sqoop/validation/Message.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/validation/Message.java 
b/common/src/main/java/org/apache/sqoop/validation/Message.java
new file mode 100644
index 0000000..cb55b6a
--- /dev/null
+++ b/common/src/main/java/org/apache/sqoop/validation/Message.java
@@ -0,0 +1,68 @@
+/**
+ * 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;
+
+/**
+ * Validation message.
+ *
+ * Validation message have always two parts - severity and textual information 
about what
+ * is wrong. It can be associated with Input, Form or Configuration class.
+ */
+public class Message {
+  private Status status;
+  private String message;
+
+  public Message(Status status, String message) {
+    this.status = status;
+    this.message = message;
+  }
+
+  public Status getStatus() {
+    return status;
+  }
+
+  public String getMessage() {
+    return message;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (!(o instanceof Message)) return false;
+
+    Message message1 = (Message) o;
+
+    if (message != null ? !message.equals(message1.message) : message1.message 
!= null)
+      return false;
+    if (status != message1.status) return false;
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = status != null ? status.hashCode() : 0;
+    result = 31 * result + (message != null ? message.hashCode() : 0);
+    return result;
+  }
+
+  @Override
+  public String toString() {
+    return "{" + status.name() + ": " + message + "}";
+  }
+}

http://git-wip-us.apache.org/repos/asf/sqoop/blob/1a0e04ec/common/src/main/java/org/apache/sqoop/validation/Status.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/validation/Status.java 
b/common/src/main/java/org/apache/sqoop/validation/Status.java
index c6f25f0..ae89e59 100644
--- a/common/src/main/java/org/apache/sqoop/validation/Status.java
+++ b/common/src/main/java/org/apache/sqoop/validation/Status.java
@@ -19,24 +19,26 @@ package org.apache.sqoop.validation;
 
 /**
  * Status modes of a validation process.
+ *
+ * TODO: This should really be renamed to "severity"
  */
 public enum Status {
   /**
    * There are no issues, no warnings. Everything is correct.
    */
-  FINE,
+  FINE, // TODO: Rename to "OK"
 
   /**
    * Validated entity is correct enough to be processed. There might be some
    * warnings, but no errors.
    */
-  ACCEPTABLE,
+  ACCEPTABLE, // TODO: Rename to "WARNING"
 
   /**
    * There are serious issues with validated entity. We can't proceed until
    * reported issues will be resolved.
    */
-  UNACCEPTABLE,
+  UNACCEPTABLE, // TODO: Rename to "ERROR"
 
   ;
 

http://git-wip-us.apache.org/repos/asf/sqoop/blob/1a0e04ec/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
new file mode 100644
index 0000000..2adfe6c
--- /dev/null
+++ 
b/common/src/main/java/org/apache/sqoop/validation/validators/ClassAvailable.java
@@ -0,0 +1,35 @@
+/**
+ * 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;
+
+/**
+ * Ensure that given String Input is a class that is available to this JVM.
+ */
+public class ClassAvailable extends Validator<String> {
+  @Override
+  public void validate(String klass) {
+    try {
+      Class.forName(klass);
+    } catch (ClassNotFoundException e) {
+      addMessage(new Message(Status.UNACCEPTABLE, "Class not found"));
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/sqoop/blob/1a0e04ec/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
new file mode 100644
index 0000000..520beea
--- /dev/null
+++ b/common/src/main/java/org/apache/sqoop/validation/validators/NotEmpty.java
@@ -0,0 +1,34 @@
+/**
+ * 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;
+
+/**
+ * Ensure that given String is not empty.
+ *
+ * Will also ensure that the string is not null.
+ */
+public class NotEmpty extends Validator<String> {
+  @Override
+  public void validate(String instance) {
+    if (instance == null || instance.isEmpty()) {
+      addMessage(Status.UNACCEPTABLE, "Can't be null nor empty");
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/sqoop/blob/1a0e04ec/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
new file mode 100644
index 0000000..fb8a926
--- /dev/null
+++ b/common/src/main/java/org/apache/sqoop/validation/validators/NotNull.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;
+
+/**
+ * Ensure that given object is never null.
+ */
+public class NotNull<T> extends Validator<T> {
+  @Override
+  public void validate(T instance) {
+    if (instance == null) {
+      addMessage(Status.UNACCEPTABLE, "Can't be null");
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/sqoop/blob/1a0e04ec/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
new file mode 100644
index 0000000..5c24b1a
--- /dev/null
+++ b/common/src/main/java/org/apache/sqoop/validation/validators/Validator.java
@@ -0,0 +1,69 @@
+/**
+ * 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;
+
+  public Validator() {
+    reset();
+  }
+
+  protected void addMessage(Message msg) {
+    messages.add(msg);
+  }
+
+  protected void addMessage(Status status, String msg) {
+    messages.add(new Message(status, msg));
+  }
+
+  public List<Message> getMessages() {
+    return messages;
+  }
+
+  /**
+   * Reset validator state (all previous messages).
+   */
+  public void reset() {
+    messages = new LinkedList<Message>();
+  }
+}

http://git-wip-us.apache.org/repos/asf/sqoop/blob/1a0e04ec/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
new file mode 100644
index 0000000..511b3b4
--- /dev/null
+++ 
b/common/src/test/java/org/apache/sqoop/validation/validators/TestClassAvailable.java
@@ -0,0 +1,50 @@
+/**
+ * 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 org.junit.Test;
+
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ */
+public class TestClassAvailable {
+
+  Validator validator = new ClassAvailable();
+
+  @Test
+  public void test() {
+    List<Message> messages;
+    assertEquals(0, validator.getMessages().size());
+
+    validator.validate(ClassAvailable.class.getCanonicalName());
+    assertEquals(0, validator.getMessages().size());
+
+    validator.validate("java.lang.String");
+    assertEquals(0, validator.getMessages().size());
+
+    validator.validate("net.jarcec.super.private.project.Main");
+    assertEquals(1, validator.getMessages().size());
+    messages = validator.getMessages();
+    assertEquals(Status.UNACCEPTABLE, messages.get(0).getStatus());
+  }
+}

http://git-wip-us.apache.org/repos/asf/sqoop/blob/1a0e04ec/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
new file mode 100644
index 0000000..d225b06
--- /dev/null
+++ 
b/common/src/test/java/org/apache/sqoop/validation/validators/TestNotEmpty.java
@@ -0,0 +1,55 @@
+/**
+ * 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 org.junit.Test;
+
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ */
+public class TestNotEmpty {
+
+  Validator validator = new NotEmpty();
+
+  @Test
+  public void test() {
+    List<Message> messages;
+    assertEquals(0, validator.getMessages().size());
+
+    validator.validate("Non empty");
+    assertEquals(0, validator.getMessages().size());
+
+    validator.validate("");
+    assertEquals(1, validator.getMessages().size());
+    messages = validator.getMessages();
+    assertEquals(Status.UNACCEPTABLE, messages.get(0).getStatus());
+
+    validator.reset();
+    assertEquals(0, validator.getMessages().size());
+
+    validator.validate(null);
+    assertEquals(1, validator.getMessages().size());
+    messages = validator.getMessages();
+    assertEquals(Status.UNACCEPTABLE, messages.get(0).getStatus());
+  }
+}

http://git-wip-us.apache.org/repos/asf/sqoop/blob/1a0e04ec/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
new file mode 100644
index 0000000..9c5bed5
--- /dev/null
+++ 
b/common/src/test/java/org/apache/sqoop/validation/validators/TestNotNull.java
@@ -0,0 +1,51 @@
+/**
+ * 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 org.junit.Test;
+
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ */
+public class TestNotNull {
+
+  Validator validator = new NotNull();
+
+  @Test
+  public void test() {
+    assertEquals(0, validator.getMessages().size());
+
+    validator.validate("");
+    assertEquals(0, validator.getMessages().size());
+
+    validator.validate("Non empty");
+    assertEquals(0, validator.getMessages().size());
+
+    validator.validate(null);
+    assertEquals(1, validator.getMessages().size());
+
+    List<Message> messages = validator.getMessages();
+    Message msg = messages.get(0);
+    assertEquals(Status.UNACCEPTABLE, msg.getStatus());
+  }
+}

http://git-wip-us.apache.org/repos/asf/sqoop/blob/1a0e04ec/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
new file mode 100644
index 0000000..1a5dbdd
--- /dev/null
+++ 
b/common/src/test/java/org/apache/sqoop/validation/validators/TestValidator.java
@@ -0,0 +1,57 @@
+/**
+ * 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 org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ *
+ */
+public class TestValidator {
+  public static class ValidatorImpl extends Validator<String> {
+    @Override
+    public void validate(String msg) {
+      addMessage(Status.FINE, msg);
+      addMessage(new Message(Status.UNACCEPTABLE, "Prefix: " + msg));
+    }
+  }
+
+  @Test
+  public void test() {
+    ValidatorImpl validator = new ValidatorImpl();
+
+    assertEquals(0, validator.getMessages().size());
+    validator.validate("X");
+    assertEquals(2, validator.getMessages().size());
+
+    Message msg = validator.getMessages().get(0);
+    assertEquals(Status.FINE, msg.getStatus());
+    assertEquals("X", msg.getMessage());
+
+    msg = validator.getMessages().get(1);
+    assertEquals(Status.UNACCEPTABLE, msg.getStatus());
+    assertEquals("Prefix: X", msg.getMessage());
+
+    validator.reset();
+    assertEquals(0, validator.getMessages().size());
+  }
+}

http://git-wip-us.apache.org/repos/asf/sqoop/blob/1a0e04ec/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 c354494..e513770 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,17 +19,44 @@ package org.apache.sqoop.connector.jdbc.configuration;
 
 import org.apache.sqoop.model.FormClass;
 import org.apache.sqoop.model.Input;
+import org.apache.sqoop.validation.Status;
+import org.apache.sqoop.validation.validators.NotEmpty;
+import org.apache.sqoop.validation.validators.Validator;
+import org.apache.sqoop.validation.validators.ClassAvailable;
 
+import java.sql.DriverManager;
+import java.sql.SQLException;
 import java.util.Map;
 
 /**
  *
  */
-@FormClass
+@FormClass(validators = {ConnectionForm.FormValidator.class})
 public class ConnectionForm {
-  @Input(size = 128) public String jdbcDriver;
-  @Input(size = 128) public String connectionString;
-  @Input(size = 40)  public String username;
-  @Input(size = 40, sensitive = true) public String password;
-  @Input public Map<String, String> jdbcProperties;
+  @Input(size = 128, validators = {NotEmpty.class, ClassAvailable.class} )
+  public String jdbcDriver;
+
+  @Input(size = 128, validators = {NotEmpty.class} )
+  public String connectionString;
+
+  @Input(size = 40)
+  public String username;
+
+  @Input(size = 40, sensitive = true)
+  public String password;
+
+  @Input
+  public Map<String, String> jdbcProperties;
+
+  public static class FormValidator extends Validator<ConnectionForm> {
+    @Override
+    public void validate(ConnectionForm form) {
+      // See if we can connect to the database
+      try {
+        DriverManager.getConnection(form.connectionString, form.username, 
form.password);
+      } catch (SQLException e) {
+        addMessage(Status.ACCEPTABLE, "Can't connect to the database with 
given credentials: " + e.getMessage());
+      }
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/1a0e04ec/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 8f6fb60..1c0b429 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
@@ -17,19 +17,59 @@
  */
 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.validation.Status;
+import org.apache.sqoop.validation.validators.Validator;
 
 /**
  *
  */
-@FormClass
+@FormClass( validators = {FromTableForm.FormValidator.class})
 public class FromTableForm {
-  @Input(size = 50)   public String schemaName;
-  @Input(size = 50)   public String tableName;
-  @Input(size = 2000) public String sql;
-  @Input(size = 50)   public String columns;
-  @Input(size = 50)   public String partitionColumn;
-  @Input              public Boolean partitionColumnNull;
-  @Input(size = 50)   public String boundaryQuery;
+  @Input(size = 50)
+  public String schemaName;
+
+  @Input(size = 50)
+  public String tableName;
+
+  @Input(size = 2000, validators = {SqlConditionTokenValidator.class})
+  public String sql;
+
+  @Input(size = 50)
+  public String columns;
+
+  @Input(size = 50)
+  public String partitionColumn;
+
+  @Input
+  public Boolean partitionColumnNull;
+
+  @Input(size = 50)
+  public String boundaryQuery;
+
+  public static class FormValidator extends Validator<FromTableForm> {
+    @Override
+    public void validate(FromTableForm form) {
+      if(form.tableName == null && form.sql == null) {
+        addMessage(Status.UNACCEPTABLE, "Either fromTable name or SQL must be 
specified");
+      }
+      if(form.tableName != null && form.sql != null) {
+        addMessage(Status.UNACCEPTABLE, "Both fromTable name and SQL cannot be 
specified");
+      }
+      if(form.schemaName != null && form.sql != null) {
+        addMessage(Status.UNACCEPTABLE, "Both schema name and SQL cannot be 
specified");
+      }
+    }
+  }
+
+  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/1a0e04ec/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 dca0bf9..0601a39 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,11 +19,13 @@ package org.apache.sqoop.connector.jdbc.configuration;
 
 import org.apache.sqoop.model.FormClass;
 import org.apache.sqoop.model.Input;
+import org.apache.sqoop.validation.Status;
+import org.apache.sqoop.validation.validators.Validator;
 
 /**
  *
  */
-@FormClass
+@FormClass(validators = {ToTableForm.FormValidator.class})
 public class ToTableForm {
   @Input(size = 50)   public String schemaName;
   @Input(size = 2000) public String tableName;
@@ -31,4 +33,22 @@ public class ToTableForm {
   @Input(size = 50)   public String columns;
   @Input(size = 2000) public String stageTableName;
   @Input              public Boolean clearStageTable;
+
+  public static class FormValidator extends Validator<ToTableForm> {
+    @Override
+    public void validate(ToTableForm form) {
+      if(form.tableName == null && form.sql == null) {
+        addMessage(Status.UNACCEPTABLE, "Either fromTable name or SQL must be 
specified");
+      }
+      if(form.tableName != null && form.sql != null) {
+        addMessage(Status.UNACCEPTABLE, "Both fromTable name and SQL cannot be 
specified");
+      }
+      if(form.tableName == null && form.stageTableName != null) {
+        addMessage(Status.UNACCEPTABLE, "Stage fromTable name cannot be 
specified without specifying fromTable name");
+      }
+      if(form.stageTableName == null && form.clearStageTable != null) {
+        addMessage(Status.UNACCEPTABLE, "Clear stage fromTable cannot be 
specified without specifying name of the stage fromTable.");
+      }
+    }
+  }
 }

Reply via email to