sqoop-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From b...@apache.org
Subject [3/4] git commit: SQOOP-662 Introduce pluggable configuration objects (Jarek Jarcec Cecho)
Date Wed, 14 Nov 2012 18:22:22 GMT
SQOOP-662 Introduce pluggable configuration objects
(Jarek Jarcec Cecho)


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

Branch: refs/heads/sqoop2
Commit: 211c67819ecf619e14fb69dfe5e8b9215680cd19
Parents: d8836af
Author: Bilung Lee <blee@apache.org>
Authored: Tue Nov 13 20:34:18 2012 -0800
Committer: Bilung Lee <blee@apache.org>
Committed: Tue Nov 13 20:34:18 2012 -0800

----------------------------------------------------------------------
 .../src/main/resources/client-resource.properties  |    4 +-
 .../java/org/apache/sqoop/model/Configuration.java |   30 ---
 .../org/apache/sqoop/model/ConfigurationClass.java |   30 +++
 .../src/main/java/org/apache/sqoop/model/Form.java |   28 +++
 .../java/org/apache/sqoop/model/FormClass.java     |   35 ++++
 .../java/org/apache/sqoop/model/FormUtils.java     |  149 ++++++++++-----
 .../main/java/org/apache/sqoop/model/Input.java    |    7 -
 .../java/org/apache/sqoop/model/MNamedElement.java |    4 +-
 .../java/org/apache/sqoop/model/ModelError.java    |    4 +-
 .../java/org/apache/sqoop/model/TestFormUtils.java |   95 ++++++----
 .../jdbc/GenericJdbcExportInitializer.java         |   21 +-
 .../jdbc/GenericJdbcImportInitializer.java         |   30 ++--
 .../sqoop/connector/jdbc/GenericJdbcValidator.java |    4 +-
 .../configuration/ConnectionConfiguration.java     |   30 +--
 .../jdbc/configuration/ConnectionForm.java         |   35 ++++
 .../jdbc/configuration/ExportJobConfiguration.java |    9 +-
 .../connector/jdbc/configuration/IgnoredForm.java  |   29 +++
 .../jdbc/configuration/ImportJobConfiguration.java |    9 +-
 .../connector/jdbc/configuration/TableForm.java    |   35 ++++
 .../generic-jdbc-connector-resources.properties    |   63 ++++---
 .../connector/jdbc/TestExportInitializer.java      |   20 +-
 .../connector/jdbc/TestImportInitializer.java      |   32 ++--
 .../apache/sqoop/framework/FrameworkConstants.java |    7 -
 .../apache/sqoop/framework/FrameworkManager.java   |   10 +-
 .../configuration/ConnectionConfiguration.java     |   11 +-
 .../configuration/ExportJobConfiguration.java      |   11 +-
 .../configuration/ImportJobConfiguration.java      |   14 +-
 .../sqoop/framework/configuration/OutputForm.java  |   32 +++
 .../framework/configuration/SecurityForm.java      |   29 +++
 .../main/resources/framework-resources.properties  |   24 ++--
 .../sqoop/handler/ConnectionRequestHandler.java    |    4 +-
 .../apache/sqoop/handler/JobRequestHandler.java    |    4 +-
 32 files changed, 563 insertions(+), 286 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/sqoop/blob/211c6781/client/src/main/resources/client-resource.properties
----------------------------------------------------------------------
diff --git a/client/src/main/resources/client-resource.properties b/client/src/main/resources/client-resource.properties
index 793ddc8..201efe9 100644
--- a/client/src/main/resources/client-resource.properties
+++ b/client/src/main/resources/client-resource.properties
@@ -18,6 +18,6 @@
 ############################
 # Security Form
 #
-object-name-label = Name
-object-name-help = Non unique name of the entity to help you remember \
+object-name.label = Name
+object-name.help = Non unique name of the entity to help you remember \
                    it's purpose

http://git-wip-us.apache.org/repos/asf/sqoop/blob/211c6781/common/src/main/java/org/apache/sqoop/model/Configuration.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/model/Configuration.java b/common/src/main/java/org/apache/sqoop/model/Configuration.java
deleted file mode 100644
index 1331c7e..0000000
--- a/common/src/main/java/org/apache/sqoop/model/Configuration.java
+++ /dev/null
@@ -1,30 +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.model;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * 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)
-public @interface Configuration {
-
-}

http://git-wip-us.apache.org/repos/asf/sqoop/blob/211c6781/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
new file mode 100644
index 0000000..5a28146
--- /dev/null
+++ b/common/src/main/java/org/apache/sqoop/model/ConfigurationClass.java
@@ -0,0 +1,30 @@
+/**
+ * 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 java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * 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)
+public @interface ConfigurationClass {
+
+}

http://git-wip-us.apache.org/repos/asf/sqoop/blob/211c6781/common/src/main/java/org/apache/sqoop/model/Form.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/model/Form.java b/common/src/main/java/org/apache/sqoop/model/Form.java
new file mode 100644
index 0000000..4321582
--- /dev/null
+++ b/common/src/main/java/org/apache/sqoop/model/Form.java
@@ -0,0 +1,28 @@
+/**
+ * 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 java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Denote form in Configuration class
+ */
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Form {
+}

http://git-wip-us.apache.org/repos/asf/sqoop/blob/211c6781/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
new file mode 100644
index 0000000..d510ca0
--- /dev/null
+++ b/common/src/main/java/org/apache/sqoop/model/FormClass.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.model;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Denote configuration class
+ */
+@Retention(RetentionPolicy.RUNTIME)
+public @interface FormClass {
+
+  /**
+   * Default size for Inputs in this form.
+   *
+   * @return
+   */
+  short defaultSize() default -1;
+}

http://git-wip-us.apache.org/repos/asf/sqoop/blob/211c6781/common/src/main/java/org/apache/sqoop/model/FormUtils.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/model/FormUtils.java b/common/src/main/java/org/apache/sqoop/model/FormUtils.java
index 418b0a7..05941f6 100644
--- a/common/src/main/java/org/apache/sqoop/model/FormUtils.java
+++ b/common/src/main/java/org/apache/sqoop/model/FormUtils.java
@@ -33,6 +33,8 @@ import java.util.Map;
 /**
  * Util class for transforming data from correctly annotated configuration
  * objects to form structures and vice-versa.
+ *
+ * TODO(jarcec): JSON methods needs rewrittion!
  */
 public class FormUtils {
 
@@ -40,9 +42,8 @@ public class FormUtils {
    * Transform correctly annotated configuration object to corresponding
    * list of forms.
    *
-   * Forms will be order according to the first occurrence in the configuration
-   * class. Inputs will be also ordered based on occurrence, however
-   * interleaving of inputs from different forms is perfectly fine.
+   * Forms will be order according to the occurrence in the configuration
+   * class. Inputs will be also ordered based on occurrence.
    *
    * @param configuration Annotated arbitrary configuration object
    * @return Corresponding list of forms
@@ -57,44 +58,77 @@ public class FormUtils {
 
   @SuppressWarnings("unchecked")
   public static List<MForm> toForms(Class klass, Object configuration) {
-    Configuration global =
-      (Configuration)klass.getAnnotation(Configuration.class);
+    ConfigurationClass global =
+      (ConfigurationClass)klass.getAnnotation(ConfigurationClass.class);
 
     // Each configuration object must have this class annotation
     if(global == null) {
       throw new SqoopException(ModelError.MODEL_003,
-        "Missing annotation Configuration on class " + klass.getName());
+        "Missing annotation ConfigurationClass on class " + klass.getName());
+    }
+
+    List<MForm> forms = new LinkedList<MForm>();
+
+    // Iterate over all declared fields
+    for (Field field : klass.getDeclaredFields()) {
+      field.setAccessible(true);
+
+      String formName = field.getName();
+
+      // Each field that should be part of user input should have Input
+      // annotation.
+      Form formAnnotation = field.getAnnotation(Form.class);
+
+      if(formAnnotation != null) {
+        Class type = field.getType();
+
+        Object value = null;
+        if(configuration != null) {
+          try {
+            value = field.get(configuration);
+          } catch (IllegalAccessException e) {
+            throw new SqoopException(ModelError.MODEL_005,
+              "Can't retrieve value from " + field.getName(), e);
+          }
+        }
+
+        forms.add(toForm(formName, type, value));
+      }
     }
 
-    // List of forms in order they appeared in configuration class
-    List<String> forms = new LinkedList<String>();
+    return forms;
+  }
+
+  @SuppressWarnings("unchecked")
+  private static MForm toForm(String formName, Class klass, Object object) {
+     FormClass global =
+      (FormClass)klass.getAnnotation(FormClass.class);
+
+    // Each configuration object must have this class annotation
+    if(global == null) {
+      throw new SqoopException(ModelError.MODEL_003,
+        "Missing annotation FormClass on class " + klass.getName());
+    }
 
-    // Intermediate list of inputs for each defined form
-    Map<String, List<MInput<?>>> formInputs
-      = new HashMap<String, List<MInput<?>>>();
+    // Intermediate list of inputs
+    List<MInput<?>> inputs = new LinkedList<MInput<?>>();
 
     // Iterate over all declared fields
     for (Field field : klass.getDeclaredFields()) {
       field.setAccessible(true);
 
       String fieldName = field.getName();
+      String inputName = formName + "." + fieldName;
 
       // Each field that should be part of user input should have Input
       // annotation.
       Input inputAnnotation = field.getAnnotation(Input.class);
 
       if(inputAnnotation != null) {
-        String form = inputAnnotation.form();
         boolean sensitive = inputAnnotation.sensitive();
         short maxLen = inputAnnotation.size();
         Class type = field.getType();
 
-        // Make sure that we will create new entries for newly discovered forms
-        if(!forms.contains(form)) {
-          forms.add(form);
-          formInputs.put(form, new LinkedList<MInput<?>>());
-        }
-
         MInput input;
 
         // We need to support NULL, so we do not support primitive types
@@ -105,26 +139,26 @@ public class FormUtils {
 
         // Instantiate corresponding MInput<?> structure
         if(type == String.class) {
-          input = new MStringInput(fieldName, sensitive, maxLen);
+          input = new MStringInput(inputName, sensitive, maxLen);
         } else if (type.isAssignableFrom(Map.class)) {
-          input = new MMapInput(fieldName);
+          input = new MMapInput(inputName);
         } else if(type == Integer.class) {
-          input = new MIntegerInput(fieldName);
+          input = new MIntegerInput(inputName);
         } else if(type.isEnum()) {
-          input = new MEnumInput(fieldName, ClassUtils.getEnumStrings(type));
+          input = new MEnumInput(inputName, ClassUtils.getEnumStrings(type));
         } else {
           throw new SqoopException(ModelError.MODEL_004,
             "Unsupported type " + type.getName() + " for input " + fieldName);
         }
 
         // Move value if it's present in original configuration object
-        if(configuration != null) {
+        if(object != null) {
           Object value;
           try {
-            value = field.get(configuration);
+            value = field.get(object);
           } catch (IllegalAccessException e) {
             throw new SqoopException(ModelError.MODEL_005,
-              "Issue with field " + field.getName(), e);
+              "Can't retrieve value from " + field.getName(), e);
           }
           if(value == null) {
             input.setEmpty();
@@ -133,17 +167,11 @@ public class FormUtils {
           }
         }
 
-        formInputs.get(form).add(input);
+        inputs.add(input);
       }
     }
 
-    // Create corresponding forms based on our intermediate structures
-    List<MForm> ret = new LinkedList<MForm>();
-    for (String form : forms) {
-      ret.add(new MForm(form, formInputs.get(form)));
-    }
-
-    return ret;
+    return new MForm(formName, inputs);
   }
 
   /**
@@ -152,38 +180,71 @@ public class FormUtils {
    * @param forms Input form list
    * @param configuration Output configuration object
    */
-  public static void fillValues(List<MForm> forms, Object configuration) {
+  public static void fromForms(List<MForm> forms, Object configuration) {
     Class klass = configuration.getClass();
 
     for(MForm form : forms) {
+      Field formField;
+      try {
+        formField = klass.getDeclaredField(form.getName());
+      } catch (NoSuchFieldException e) {
+        throw new SqoopException(ModelError.MODEL_006,
+          "Missing field " + form.getName() + " on form class " + klass.getCanonicalName(), e);
+      }
+
+      // We need to access this field even if it would be declared as private
+      formField.setAccessible(true);
+
+      Class formClass = formField.getType();
+      Object newValue = ClassUtils.instantiate(formClass);
+
+      if(newValue == null) {
+        throw new SqoopException(ModelError.MODEL_006,
+          "Can't instantiate new form " + formClass);
+      }
+
       for(MInput input : form.getInputs()) {
-        Field field;
+        String[] splitNames = input.getName().split("\\.");
+        if(splitNames.length != 2) {
+          throw new SqoopException(ModelError.MODEL_009,
+            "Invalid name: " + input.getName());
+        }
+
+        String inputName = splitNames[1];
+        // TODO(jarcec): Names structures fix, handle error cases
+        Field inputField;
         try {
-          field = klass.getDeclaredField(input.getName());
+          inputField = formClass.getDeclaredField(inputName);
         } catch (NoSuchFieldException e) {
           throw new SqoopException(ModelError.MODEL_006,
             "Missing field " + input.getName(), e);
         }
 
         // We need to access this field even if it would be declared as private
-        field.setAccessible(true);
+        inputField.setAccessible(true);
 
-        // Propagate value to the configuration object
         try {
           if(input.isEmpty()) {
-            field.set(configuration, null);
+            inputField.set(newValue, null);
           } else {
             if (input.getType() == MInputType.ENUM) {
-              field.set(configuration, Enum.valueOf((Class<? extends Enum>)field.getType(), (String) input.getValue()));
+              inputField.set(newValue, Enum.valueOf((Class<? extends Enum>)inputField.getType(), (String) input.getValue()));
             } else {
-              field.set(configuration, input.getValue());
+              inputField.set(newValue, input.getValue());
             }
           }
         } catch (IllegalAccessException e) {
           throw new SqoopException(ModelError.MODEL_005,
-            "Issue with field " + field.getName(), e);
+            "Issue with field " + inputField.getName(), e);
         }
       }
+
+      try {
+        formField.set(configuration, newValue);
+      } catch (IllegalAccessException e) {
+        throw new SqoopException(ModelError.MODEL_005,
+          "Issue with field " + formField.getName(), e);
+      }
     }
   }
 
@@ -214,8 +275,8 @@ public class FormUtils {
   public static String toJson(Object configuration) {
     Class klass = configuration.getClass();
 
-    Configuration global =
-      (Configuration)klass.getAnnotation(Configuration.class);
+    ConfigurationClass global =
+      (ConfigurationClass)klass.getAnnotation(ConfigurationClass.class);
 
     // Each configuration object must have this class annotation
     if(global == null) {

http://git-wip-us.apache.org/repos/asf/sqoop/blob/211c6781/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 6b3973b..6df2b9f 100644
--- a/common/src/main/java/org/apache/sqoop/model/Input.java
+++ b/common/src/main/java/org/apache/sqoop/model/Input.java
@@ -27,13 +27,6 @@ import java.lang.annotation.RetentionPolicy;
 @Retention(RetentionPolicy.RUNTIME)
 public @interface Input {
   /**
-   * Name of form where this input belongs.
-   *
-   * @return Form name
-   */
-  String form();
-
-  /**
    * Sqoop framework will ensure that sensitive information will not be easily
    * accessible.
    *

http://git-wip-us.apache.org/repos/asf/sqoop/blob/211c6781/common/src/main/java/org/apache/sqoop/model/MNamedElement.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/model/MNamedElement.java b/common/src/main/java/org/apache/sqoop/model/MNamedElement.java
index e67a78c..42c9954 100644
--- a/common/src/main/java/org/apache/sqoop/model/MNamedElement.java
+++ b/common/src/main/java/org/apache/sqoop/model/MNamedElement.java
@@ -21,8 +21,8 @@ package org.apache.sqoop.model;
  * Represents an element of metadata used by the connector.
  */
 public abstract class MNamedElement extends MPersistableEntity {
-  private static final String LABEL_KEY_SUFFIX = "-label";
-  private static final String HELP_KEY_SUFFIX = "-help";
+  private static final String LABEL_KEY_SUFFIX = ".label";
+  private static final String HELP_KEY_SUFFIX = ".help";
 
   private final String name;
   private final String labelKey;

http://git-wip-us.apache.org/repos/asf/sqoop/blob/211c6781/common/src/main/java/org/apache/sqoop/model/ModelError.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/model/ModelError.java b/common/src/main/java/org/apache/sqoop/model/ModelError.java
index 2c496ce..f8d61ef 100644
--- a/common/src/main/java/org/apache/sqoop/model/ModelError.java
+++ b/common/src/main/java/org/apache/sqoop/model/ModelError.java
@@ -32,7 +32,7 @@ public enum ModelError implements ErrorCode {
 
   MODEL_004("Usage of unsupported data type"),
 
-  MODEL_005("Can't get field details"),
+  MODEL_005("Can't get field value"),
 
   MODEL_006("Incompatible form list and configuration object"),
 
@@ -40,6 +40,8 @@ public enum ModelError implements ErrorCode {
 
   MODEL_008("Invalid input value"),
 
+  MODEL_009("Invalid input name"),
+
   ;
 
   private final String message;

http://git-wip-us.apache.org/repos/asf/sqoop/blob/211c6781/common/src/test/java/org/apache/sqoop/model/TestFormUtils.java
----------------------------------------------------------------------
diff --git a/common/src/test/java/org/apache/sqoop/model/TestFormUtils.java b/common/src/test/java/org/apache/sqoop/model/TestFormUtils.java
index c19f9bd..f17155f 100644
--- a/common/src/test/java/org/apache/sqoop/model/TestFormUtils.java
+++ b/common/src/test/java/org/apache/sqoop/model/TestFormUtils.java
@@ -34,7 +34,7 @@ public class TestFormUtils extends TestCase {
 
   public void testToForms() {
     Config config = new Config();
-    config.a1 = "value";
+    config.aForm.a1 = "value";
 
     List<MForm> formsByInstance = FormUtils.toForms(config);
     assertEquals(getForms(), formsByInstance);
@@ -77,8 +77,8 @@ public class TestFormUtils extends TestCase {
 
     Config config = new Config();
 
-    FormUtils.fillValues(forms, config);
-    assertEquals("value", config.a1);
+    FormUtils.fromForms(forms, config);
+    assertEquals("value", config.aForm.a1);
   }
 
   public void testFillValuesObjectReuse() {
@@ -87,14 +87,14 @@ public class TestFormUtils extends TestCase {
     ((MStringInput)forms.get(0).getInputs().get(0)).setValue("value");
 
     Config config = new Config();
-    config.a2 = "x";
-    config.b1 = "y";
-
-    FormUtils.fillValues(forms, config);
-    assertEquals("value", config.a1);
-    assertNull(config.a2);
-    assertNull(config.b2);
-    assertNull(config.b2);
+    config.aForm.a2 = "x";
+    config.bForm.b1 = "y";
+
+    FormUtils.fromForms(forms, config);
+    assertEquals("value", config.aForm.a1);
+    assertNull(config.aForm.a2);
+    assertNull(config.bForm.b2);
+    assertNull(config.bForm.b2);
   }
 
   public void testApplyValidation() {
@@ -118,8 +118,8 @@ public class TestFormUtils extends TestCase {
     Map<String, Validation.Message> messages
       = new HashMap<String, Validation.Message>();
 
-    messages.put("a1", new Validation.Message(Status.ACCEPTABLE, "e1"));
-    messages.put("a2", new Validation.Message(Status.UNACCEPTABLE, "e2"));
+    messages.put("aForm.a1", new Validation.Message(Status.ACCEPTABLE, "e1"));
+    messages.put("aForm.a2", new Validation.Message(Status.UNACCEPTABLE, "e2"));
 
     return new Validation(Status.UNACCEPTABLE, messages);
   }
@@ -135,40 +135,67 @@ public class TestFormUtils extends TestCase {
 
     // Form A
     inputs = new LinkedList<MInput<?>>();
-    inputs.add(new MStringInput("a1", false, (short)30));
-    inputs.add(new MStringInput("a2", true, (short)-1));
-    ret.add(new MForm("A", inputs));
+    inputs.add(new MStringInput("aForm.a1", false, (short)30));
+    inputs.add(new MStringInput("aForm.a2", true, (short)-1));
+    ret.add(new MForm("aForm", inputs));
 
     // Form B
     inputs = new LinkedList<MInput<?>>();
-    inputs.add(new MStringInput("b1", false, (short)2));
-    inputs.add(new MStringInput("b2", false, (short)3));
-    ret.add(new MForm("B", inputs));
+    inputs.add(new MStringInput("bForm.b1", false, (short)2));
+    inputs.add(new MStringInput("bForm.b2", false, (short)3));
+    ret.add(new MForm("bForm", inputs));
 
     // Form C
     inputs = new LinkedList<MInput<?>>();
-    inputs.add(new MIntegerInput("intValue"));
-    inputs.add(new MMapInput("map"));
-    ret.add(new MForm("C", inputs));
+    inputs.add(new MIntegerInput("cForm.intValue"));
+    inputs.add(new MMapInput("cForm.map"));
+    ret.add(new MForm("cForm", inputs));
 
     return ret;
   }
 
-  @Configuration
-  class Config {
-    @Input(form = "A", size = 30)  String a1;
-    @Input(form = "A", sensitive = true)  String a2;
-    @Input(form = "B", size = 2)  String b1;
-    @Input(form = "B", size = 3)  String b2;
-    @Input(form = "C") Integer intValue;
-    @Input(form = "C") Map<String, String> map;
+  @ConfigurationClass
+  public static class Config {
+
+    public Config() {
+      aForm = new AForm();
+      bForm = new BForm();
+      cForm = new CForm();
+    }
+
+    @Form AForm aForm;
+    @Form BForm bForm;
+    @Form CForm cForm;
+  }
+
+  @ConfigurationClass
+  public static class PrimitiveConfig {
+    @Form DForm dForm;
+  }
+
+  @FormClass
+  public static class AForm {
+    @Input(size = 30)  String a1;
+    @Input(sensitive = true)  String a2;
+  }
+
+  @FormClass
+  public static class BForm {
+    @Input(size = 2) String b1;
+    @Input(size = 3) String b2;
+  }
+
+  @FormClass
+  public static class CForm {
+    @Input Integer intValue;
+    @Input Map<String, String> map;
   }
 
-  @Configuration
-  class PrimitiveConfig {
-    @Input(form = "A") int value;
+  @FormClass
+  public static class DForm {
+    @Input int value;
   }
 
-  class ConfigWithout {
+  public static class ConfigWithout {
   }
 }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/211c6781/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/GenericJdbcExportInitializer.java
----------------------------------------------------------------------
diff --git a/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/GenericJdbcExportInitializer.java b/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/GenericJdbcExportInitializer.java
index 72b992c..9199e75 100644
--- a/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/GenericJdbcExportInitializer.java
+++ b/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/GenericJdbcExportInitializer.java
@@ -26,7 +26,6 @@ import org.apache.sqoop.common.MutableContext;
 import org.apache.sqoop.common.SqoopException;
 import org.apache.sqoop.connector.jdbc.configuration.ConnectionConfiguration;
 import org.apache.sqoop.connector.jdbc.configuration.ExportJobConfiguration;
-import org.apache.sqoop.connector.jdbc.configuration.ImportJobConfiguration;
 import org.apache.sqoop.job.Constants;
 import org.apache.sqoop.job.etl.Initializer;
 import org.apache.sqoop.utils.ClassUtils;
@@ -54,16 +53,16 @@ public class GenericJdbcExportInitializer extends Initializer {
     List<String> jars = new LinkedList<String>();
 
     ConnectionConfiguration connection = (ConnectionConfiguration) connectionConfiguration;
-    jars.add(ClassUtils.jarForClass(connection.jdbcDriver));
+    jars.add(ClassUtils.jarForClass(connection.connection.jdbcDriver));
 
     return jars;
   }
 
   private void configureJdbcProperties(MutableContext context, ConnectionConfiguration connectionConfig, ExportJobConfiguration jobConfig) {
-    String driver = connectionConfig.jdbcDriver;
-    String url = connectionConfig.connectionString;
-    String username = connectionConfig.username;
-    String password = connectionConfig.password;
+    String driver = connectionConfig.connection.jdbcDriver;
+    String url = connectionConfig.connection.connectionString;
+    String username = connectionConfig.connection.username;
+    String password = connectionConfig.connection.password;
 
     if (driver == null) {
       throw new SqoopException(
@@ -102,12 +101,12 @@ public class GenericJdbcExportInitializer extends Initializer {
     String dataSql;
     String inputDirectory;
 
-    String tableName = connectionConfig.tableName;
-    String tableSql = connectionConfig.sql;
-    String tableColumns = connectionConfig.columns;
+    String tableName = connectionConfig.table.tableName;
+    String tableSql = connectionConfig.table.sql;
+    String tableColumns = connectionConfig.table.columns;
 
-    String datadir = connectionConfig.dataDirectory;
-    String warehouse = connectionConfig.warehouse;
+    String datadir = connectionConfig.table.dataDirectory;
+    String warehouse = connectionConfig.table.warehouse;
     if (warehouse == null) {
       warehouse = GenericJdbcConnectorConstants.DEFAULT_WAREHOUSE;
     } else if (!warehouse.endsWith(GenericJdbcConnectorConstants.FILE_SEPARATOR)) {

http://git-wip-us.apache.org/repos/asf/sqoop/blob/211c6781/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/GenericJdbcImportInitializer.java
----------------------------------------------------------------------
diff --git a/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/GenericJdbcImportInitializer.java b/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/GenericJdbcImportInitializer.java
index f8e941c..39f19f5 100644
--- a/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/GenericJdbcImportInitializer.java
+++ b/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/GenericJdbcImportInitializer.java
@@ -62,16 +62,16 @@ public class GenericJdbcImportInitializer extends Initializer {
     List<String> jars = new LinkedList<String>();
 
     ConnectionConfiguration connection = (ConnectionConfiguration) connectionConfiguration;
-    jars.add(ClassUtils.jarForClass(connection.jdbcDriver));
+    jars.add(ClassUtils.jarForClass(connection.connection.jdbcDriver));
 
     return jars;
   }
 
   private void configureJdbcProperties(MutableContext context, ConnectionConfiguration connectionConfig, ImportJobConfiguration jobConfig) {
-    String driver = connectionConfig.jdbcDriver;
-    String url = connectionConfig.connectionString;
-    String username = connectionConfig.username;
-    String password = connectionConfig.password;
+    String driver = connectionConfig.connection.jdbcDriver;
+    String url = connectionConfig.connection.connectionString;
+    String username = connectionConfig.connection.username;
+    String password = connectionConfig.connection.password;
 
     // TODO(jarcec): Those checks should be in validator and not here
     if (driver == null) {
@@ -110,12 +110,12 @@ public class GenericJdbcImportInitializer extends Initializer {
   private void configurePartitionProperties(MutableContext context, ConnectionConfiguration connectionConfig, ImportJobConfiguration jobConfig) {
     // ----- configure column name -----
 
-    String partitionColumnName = connectionConfig.partitionColumn;
+    String partitionColumnName = connectionConfig.table.partitionColumn;
 
     if (partitionColumnName == null) {
       // if column is not specified by the user,
       // find the primary key of the table (when there is a table).
-      String tableName = connectionConfig.tableName;
+      String tableName = connectionConfig.table.tableName;
       if (tableName != null) {
         partitionColumnName = executor.getPrimaryKey(tableName);
       }
@@ -133,13 +133,13 @@ public class GenericJdbcImportInitializer extends Initializer {
 
     // ----- configure column type, min value, and max value -----
 
-    String minMaxQuery = connectionConfig.boundaryQuery;
+    String minMaxQuery = connectionConfig.table.boundaryQuery;
 
     if (minMaxQuery == null) {
       StringBuilder builder = new StringBuilder();
 
-      String tableName = connectionConfig.tableName;
-      String tableSql = connectionConfig.sql;
+      String tableName = connectionConfig.table.tableName;
+      String tableSql = connectionConfig.table.sql;
 
       if (tableName != null && tableSql != null) {
         // when both table name and table sql are specified:
@@ -212,13 +212,13 @@ public class GenericJdbcImportInitializer extends Initializer {
     String fieldNames;
     String outputDirectory;
 
-    String tableName = connectionConfig.tableName;
-    String tableSql = connectionConfig.sql;
-    String tableColumns = connectionConfig.columns;
+    String tableName = connectionConfig.table.tableName;
+    String tableSql = connectionConfig.table.sql;
+    String tableColumns = connectionConfig.table.columns;
 
     //TODO(jarcec): Why is connector concerned with data directory? It should not need it at all!
-    String datadir = connectionConfig.dataDirectory;
-    String warehouse = connectionConfig.warehouse;
+    String datadir = connectionConfig.table.dataDirectory;
+    String warehouse = connectionConfig.table.warehouse;
     if (warehouse == null) {
       warehouse = GenericJdbcConnectorConstants.DEFAULT_WAREHOUSE;
     } else if (!warehouse.endsWith(GenericJdbcConnectorConstants.FILE_SEPARATOR)) {

http://git-wip-us.apache.org/repos/asf/sqoop/blob/211c6781/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/GenericJdbcValidator.java
----------------------------------------------------------------------
diff --git a/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/GenericJdbcValidator.java b/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/GenericJdbcValidator.java
index a6e7bbf..52ad2dc 100644
--- a/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/GenericJdbcValidator.java
+++ b/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/GenericJdbcValidator.java
@@ -32,8 +32,8 @@ public class GenericJdbcValidator extends Validator {
     Validation validation = new Validation(ConnectionConfiguration.class);
     ConnectionConfiguration config = (ConnectionConfiguration)configuration;
 
-    if(config.connectionString == null
-      || !config.connectionString.startsWith("jdbc:")) {
+    if(config.connection.connectionString == null
+      || !config.connection.connectionString.startsWith("jdbc:")) {
       validation.addMessage(Status.UNACCEPTABLE, "connectionString",
         "This do not seem as a valid JDBC URL");
     }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/211c6781/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/configuration/ConnectionConfiguration.java
----------------------------------------------------------------------
diff --git a/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/configuration/ConnectionConfiguration.java b/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/configuration/ConnectionConfiguration.java
index f9b8e1b..5057cf5 100644
--- a/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/configuration/ConnectionConfiguration.java
+++ b/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/configuration/ConnectionConfiguration.java
@@ -17,31 +17,21 @@
  */
 package org.apache.sqoop.connector.jdbc.configuration;
 
-import org.apache.sqoop.model.Configuration;
-import org.apache.sqoop.model.Input;
-
-import java.util.Map;
-
-import static org.apache.sqoop.connector.jdbc.GenericJdbcConnectorConstants.*;
+import org.apache.sqoop.model.ConfigurationClass;
+import org.apache.sqoop.model.Form;
 
 /**
  *
  */
-@Configuration
+@ConfigurationClass
 public class ConnectionConfiguration {
-  @Input(form = FORM_CONNECTION, size = 128) public String jdbcDriver;
-  @Input(form = FORM_CONNECTION, size = 128) public String connectionString;
-  @Input(form = FORM_CONNECTION, size = 40)  public String username;
-  @Input(form = FORM_CONNECTION, size = 40, sensitive = true) public String password;
 
-  @Input(form = FORM_CONNECTION) public Map<String, String> jdbcProperties;
+  @Form public ConnectionForm connection;
+
+  @Form public TableForm table;
 
-  //TODO(jarcec): Those parameters should be moved to job configuration!
-  @Input(form = FORM_TABLE, size = 50) public String tableName;
-  @Input(form = FORM_TABLE, size = 50) public String sql;
-  @Input(form = FORM_TABLE, size = 50) public String columns;
-  @Input(form = FORM_TABLE, size = 50) public String warehouse;
-  @Input(form = FORM_TABLE, size = 50) public String dataDirectory;
-  @Input(form = FORM_TABLE, size = 50) public String partitionColumn;
-  @Input(form = FORM_TABLE, size = 50) public String boundaryQuery;
+  public ConnectionConfiguration() {
+    connection = new ConnectionForm();
+    table = new TableForm();
+  }
 }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/211c6781/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
new file mode 100644
index 0000000..c354494
--- /dev/null
+++ b/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/configuration/ConnectionForm.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.connector.jdbc.configuration;
+
+import org.apache.sqoop.model.FormClass;
+import org.apache.sqoop.model.Input;
+
+import java.util.Map;
+
+/**
+ *
+ */
+@FormClass
+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;
+}

http://git-wip-us.apache.org/repos/asf/sqoop/blob/211c6781/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/configuration/ExportJobConfiguration.java
----------------------------------------------------------------------
diff --git a/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/configuration/ExportJobConfiguration.java b/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/configuration/ExportJobConfiguration.java
index e54e7db..c32b066 100644
--- a/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/configuration/ExportJobConfiguration.java
+++ b/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/configuration/ExportJobConfiguration.java
@@ -17,14 +17,13 @@
  */
 package org.apache.sqoop.connector.jdbc.configuration;
 
-import org.apache.sqoop.model.Configuration;
-import org.apache.sqoop.model.Input;
+import org.apache.sqoop.model.ConfigurationClass;
+import org.apache.sqoop.model.Form;
 
 /**
  *
  */
-@Configuration
+@ConfigurationClass
 public class ExportJobConfiguration {
-  @Input(form = "ignored")
-  String ignored;
+  @Form IgnoredForm ignored;
 }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/211c6781/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/configuration/IgnoredForm.java
----------------------------------------------------------------------
diff --git a/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/configuration/IgnoredForm.java b/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/configuration/IgnoredForm.java
new file mode 100644
index 0000000..8c04318
--- /dev/null
+++ b/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/configuration/IgnoredForm.java
@@ -0,0 +1,29 @@
+/**
+ * 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.connector.jdbc.configuration;
+
+import org.apache.sqoop.model.FormClass;
+import org.apache.sqoop.model.Input;
+
+/**
+ *
+ */
+@FormClass
+public class IgnoredForm {
+  @Input public String ignored;
+}

http://git-wip-us.apache.org/repos/asf/sqoop/blob/211c6781/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/configuration/ImportJobConfiguration.java
----------------------------------------------------------------------
diff --git a/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/configuration/ImportJobConfiguration.java b/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/configuration/ImportJobConfiguration.java
index b03cdbd..11b1c5f 100644
--- a/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/configuration/ImportJobConfiguration.java
+++ b/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/configuration/ImportJobConfiguration.java
@@ -17,14 +17,13 @@
  */
 package org.apache.sqoop.connector.jdbc.configuration;
 
-import org.apache.sqoop.model.Configuration;
-import org.apache.sqoop.model.Input;
+import org.apache.sqoop.model.ConfigurationClass;
+import org.apache.sqoop.model.Form;
 
 /**
  *
  */
-@Configuration
+@ConfigurationClass
 public class ImportJobConfiguration {
-  @Input(form = "ignored")
-  String ignored;
+  @Form IgnoredForm ignored;
 }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/211c6781/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/configuration/TableForm.java
----------------------------------------------------------------------
diff --git a/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/configuration/TableForm.java b/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/configuration/TableForm.java
new file mode 100644
index 0000000..9eb6a01
--- /dev/null
+++ b/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/configuration/TableForm.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.connector.jdbc.configuration;
+
+import org.apache.sqoop.model.FormClass;
+import org.apache.sqoop.model.Input;
+
+/**
+ *
+ */
+@FormClass
+public class TableForm {
+  @Input(size = 50) public String tableName;
+  @Input(size = 50) public String sql;
+  @Input(size = 50) public String columns;
+  @Input(size = 50) public String warehouse;
+  @Input(size = 50) public String dataDirectory;
+  @Input(size = 50) public String partitionColumn;
+  @Input(size = 50) public String boundaryQuery;
+}

http://git-wip-us.apache.org/repos/asf/sqoop/blob/211c6781/connector/connector-generic-jdbc/src/main/resources/generic-jdbc-connector-resources.properties
----------------------------------------------------------------------
diff --git a/connector/connector-generic-jdbc/src/main/resources/generic-jdbc-connector-resources.properties b/connector/connector-generic-jdbc/src/main/resources/generic-jdbc-connector-resources.properties
index 9b0b9ab..0372911 100644
--- a/connector/connector-generic-jdbc/src/main/resources/generic-jdbc-connector-resources.properties
+++ b/connector/connector-generic-jdbc/src/main/resources/generic-jdbc-connector-resources.properties
@@ -18,69 +18,72 @@
 ############################
 # Connection Form
 #
-form-connection-label = Configuration configuration
-form-connection-help = You must supply the information requested in order to \
+connection.label = Configuration configuration
+connection.help = You must supply the information requested in order to \
                    create a connection object.
 
 # jdbc driver
-jdbcDriver-label = JDBC Driver Class
-jdbcDriver-help = Enter the fully qualified class name of the JDBC \
+connection.jdbcDriver.label = JDBC Driver Class
+connection.jdbcDriver.help = Enter the fully qualified class name of the JDBC \
                    driver that will be used for establishing this connection.
 
 # connect string
-connectionString-label = JDBC Connection String
-connectionString-help = Enter the value of JDBC connection string to be \
+connection.connectionString.label = JDBC Connection String
+connection.connectionString.help = Enter the value of JDBC connection string to be \
                    used by this connector for creating connections.
 
 # username string
-username-label = Username
-username-help = Enter the username to be used for connecting to the \
+connection.username.label = Username
+connection.username.help = Enter the username to be used for connecting to the \
                    database.
 
 # password string
-password-label = Password
-password-help = Enter the password to be used for connecting to the \
+connection.password.label = Password
+connection.password.help = Enter the password to be used for connecting to the \
                    database.
 
 # jdbc properties
-jdbcProperties-label = JDBC Connection Properties
-jdbcProperties-help = Enter any JDBC properties that should be \
+connection.jdbcProperties.label = JDBC Connection Properties
+connection.jdbcProperties.help = Enter any JDBC properties that should be \
                    supplied during the creation of connection.
 
 # Table From
 #
-form-table-label = Database configuration
-form-table-help = You must supply the information requested in order to create \
+table.label = Database configuration
+table.help = You must supply the information requested in order to create \
                   a connection object.
 
 # Table name
-tableName-label = Table name
-tableName-help = Table name to process data in the remote database
+table.tableName.label = Table name
+table.tableName.help = Table name to process data in the remote database
 
 # Table SQL
-sql-label = Table SQL statement
-sql-help = SQL statement to process data in the remote database
+table.sql.label = Table SQL statement
+table.sql.help = SQL statement to process data in the remote database
 
 # Table columns
-columns-label = Table column names
-columns-help = Specific columns of a table name or a table SQL
+table.columns.label = Table column names
+table.columns.help = Specific columns of a table name or a table SQL
 
 # Table warehouse
-warehouse-label = Data warehouse
-warehouse-help = The root directory for data
+table.warehouse.label = Data warehouse
+table.warehouse.help = The root directory for data
 
 # Table datadir
-dataDirectory-label = Data directory
-dataDirectory-help = The sub-directory under warehouse for data
+table.dataDirectory.label = Data directory
+table.dataDirectory.help = The sub-directory under warehouse for data
 
 # Table pcol
-partitionColumn-label = Partition column name
-partitionColumn-help = A specific column for data partition
+table.partitionColumn.label = Partition column name
+table.partitionColumn.help = A specific column for data partition
 
 # Table boundary
-boundaryQuery-label = Boundary query
-boundaryQuery-help = The boundary query for data partition
+table.boundaryQuery.label = Boundary query
+table.boundaryQuery.help = The boundary query for data partition
 
 # Placeholders to have some entities created
-ignored-label = Ignored
-ignored-help = This is completely ignored
+ignored.label = Ignored
+ignored.help = This is completely ignored
+
+ignored.ignored.label = Ignored
+ignored.ignored.help = This is completely ignored

http://git-wip-us.apache.org/repos/asf/sqoop/blob/211c6781/connector/connector-generic-jdbc/src/test/java/org/apache/sqoop/connector/jdbc/TestExportInitializer.java
----------------------------------------------------------------------
diff --git a/connector/connector-generic-jdbc/src/test/java/org/apache/sqoop/connector/jdbc/TestExportInitializer.java b/connector/connector-generic-jdbc/src/test/java/org/apache/sqoop/connector/jdbc/TestExportInitializer.java
index 24bbb41..8dbfb4b 100644
--- a/connector/connector-generic-jdbc/src/test/java/org/apache/sqoop/connector/jdbc/TestExportInitializer.java
+++ b/connector/connector-generic-jdbc/src/test/java/org/apache/sqoop/connector/jdbc/TestExportInitializer.java
@@ -59,9 +59,9 @@ public class TestExportInitializer extends TestCase {
 
   public void testTableName() throws Exception {
     ConnectionConfiguration connConf = new ConnectionConfiguration();
-    connConf.jdbcDriver = GenericJdbcTestConstants.DRIVER;
-    connConf.connectionString = GenericJdbcTestConstants.URL;
-    connConf.tableName = tableName;
+    connConf.connection.jdbcDriver = GenericJdbcTestConstants.DRIVER;
+    connConf.connection.connectionString = GenericJdbcTestConstants.URL;
+    connConf.table.tableName = tableName;
 
     ExportJobConfiguration jobConf = new ExportJobConfiguration();
 
@@ -78,10 +78,10 @@ public class TestExportInitializer extends TestCase {
 
   public void testTableNameWithTableColumns() throws Exception {
     ConnectionConfiguration connConf = new ConnectionConfiguration();
-    connConf.jdbcDriver = GenericJdbcTestConstants.DRIVER;
-    connConf.connectionString = GenericJdbcTestConstants.URL;
-    connConf.tableName = tableName;
-    connConf.columns = tableColumns;
+    connConf.connection.jdbcDriver = GenericJdbcTestConstants.DRIVER;
+    connConf.connection.connectionString = GenericJdbcTestConstants.URL;
+    connConf.table.tableName = tableName;
+    connConf.table.columns = tableColumns;
 
     ExportJobConfiguration jobConf = new ExportJobConfiguration();
 
@@ -98,9 +98,9 @@ public class TestExportInitializer extends TestCase {
 
   public void testTableSql() throws Exception {
     ConnectionConfiguration connConf = new ConnectionConfiguration();
-    connConf.jdbcDriver = GenericJdbcTestConstants.DRIVER;
-    connConf.connectionString = GenericJdbcTestConstants.URL;
-    connConf.sql = tableSql;
+    connConf.connection.jdbcDriver = GenericJdbcTestConstants.DRIVER;
+    connConf.connection.connectionString = GenericJdbcTestConstants.URL;
+    connConf.table.sql = tableSql;
 
     ExportJobConfiguration jobConf = new ExportJobConfiguration();
 

http://git-wip-us.apache.org/repos/asf/sqoop/blob/211c6781/connector/connector-generic-jdbc/src/test/java/org/apache/sqoop/connector/jdbc/TestImportInitializer.java
----------------------------------------------------------------------
diff --git a/connector/connector-generic-jdbc/src/test/java/org/apache/sqoop/connector/jdbc/TestImportInitializer.java b/connector/connector-generic-jdbc/src/test/java/org/apache/sqoop/connector/jdbc/TestImportInitializer.java
index 8957ed1..0c7be4b 100644
--- a/connector/connector-generic-jdbc/src/test/java/org/apache/sqoop/connector/jdbc/TestImportInitializer.java
+++ b/connector/connector-generic-jdbc/src/test/java/org/apache/sqoop/connector/jdbc/TestImportInitializer.java
@@ -71,9 +71,9 @@ public class TestImportInitializer extends TestCase {
 
   public void testTableName() throws Exception {
     ConnectionConfiguration connConf = new ConnectionConfiguration();
-    connConf.jdbcDriver = GenericJdbcTestConstants.DRIVER;
-    connConf.connectionString = GenericJdbcTestConstants.URL;
-    connConf.tableName = tableName;
+    connConf.connection.jdbcDriver = GenericJdbcTestConstants.DRIVER;
+    connConf.connection.connectionString = GenericJdbcTestConstants.URL;
+    connConf.table.tableName = tableName;
 
     ImportJobConfiguration jobConf = new ImportJobConfiguration();
 
@@ -95,10 +95,10 @@ public class TestImportInitializer extends TestCase {
 
   public void testTableNameWithTableColumns() throws Exception {
     ConnectionConfiguration connConf = new ConnectionConfiguration();
-    connConf.jdbcDriver = GenericJdbcTestConstants.DRIVER;
-    connConf.connectionString = GenericJdbcTestConstants.URL;
-    connConf.tableName = tableName;
-    connConf.columns = tableColumns;
+    connConf.connection.jdbcDriver = GenericJdbcTestConstants.DRIVER;
+    connConf.connection.connectionString = GenericJdbcTestConstants.URL;
+    connConf.table.tableName = tableName;
+    connConf.table.columns = tableColumns;
 
     ImportJobConfiguration jobConf = new ImportJobConfiguration();
 
@@ -120,10 +120,10 @@ public class TestImportInitializer extends TestCase {
 
   public void testTableSql() throws Exception {
     ConnectionConfiguration connConf = new ConnectionConfiguration();
-    connConf.jdbcDriver = GenericJdbcTestConstants.DRIVER;
-    connConf.connectionString = GenericJdbcTestConstants.URL;
-    connConf.sql = tableSql;
-    connConf.partitionColumn = "DCOL";
+    connConf.connection.jdbcDriver = GenericJdbcTestConstants.DRIVER;
+    connConf.connection.connectionString = GenericJdbcTestConstants.URL;
+    connConf.table.sql = tableSql;
+    connConf.table.partitionColumn = "DCOL";
 
     ImportJobConfiguration jobConf = new ImportJobConfiguration();
 
@@ -146,11 +146,11 @@ public class TestImportInitializer extends TestCase {
 
   public void testTableSqlWithTableColumns() throws Exception {
     ConnectionConfiguration connConf = new ConnectionConfiguration();
-    connConf.jdbcDriver = GenericJdbcTestConstants.DRIVER;
-    connConf.connectionString = GenericJdbcTestConstants.URL;
-    connConf.sql = tableSql;
-    connConf.columns = tableColumns;
-    connConf.partitionColumn = "DCOL";
+    connConf.connection.jdbcDriver = GenericJdbcTestConstants.DRIVER;
+    connConf.connection.connectionString = GenericJdbcTestConstants.URL;
+    connConf.table.sql = tableSql;
+    connConf.table.columns = tableColumns;
+    connConf.table.partitionColumn = "DCOL";
 
     ImportJobConfiguration jobConf = new ImportJobConfiguration();
 

http://git-wip-us.apache.org/repos/asf/sqoop/blob/211c6781/core/src/main/java/org/apache/sqoop/framework/FrameworkConstants.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/sqoop/framework/FrameworkConstants.java b/core/src/main/java/org/apache/sqoop/framework/FrameworkConstants.java
index 32da4e8..4293dce 100644
--- a/core/src/main/java/org/apache/sqoop/framework/FrameworkConstants.java
+++ b/core/src/main/java/org/apache/sqoop/framework/FrameworkConstants.java
@@ -59,13 +59,6 @@ public final class FrameworkConstants {
   public static final String PREFIX_EXECUTION_ENGINE_CONFIG =
     SYSCFG_EXECUTION_ENGINE + ".";
 
-  // Connection/Job Configuration forms
-
-  public static final String FORM_SECURITY =
-    "form-security";
-  public static final String FORM_OUTPUT =
-    "form-output";
-
   // Bundle names
 
   public static final String RESOURCE_BUNDLE_NAME = "framework-resources";

http://git-wip-us.apache.org/repos/asf/sqoop/blob/211c6781/core/src/main/java/org/apache/sqoop/framework/FrameworkManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/sqoop/framework/FrameworkManager.java b/core/src/main/java/org/apache/sqoop/framework/FrameworkManager.java
index d04a100..c9c9cf4 100644
--- a/core/src/main/java/org/apache/sqoop/framework/FrameworkManager.java
+++ b/core/src/main/java/org/apache/sqoop/framework/FrameworkManager.java
@@ -288,22 +288,22 @@ public final class FrameworkManager {
     // Transform forms to connector specific classes
     Object connectorConnection = ClassUtils.instantiate(
       connector.getConnectionConfigurationClass());
-    FormUtils.fillValues(connection.getConnectorPart().getForms(),
+    FormUtils.fromForms(connection.getConnectorPart().getForms(),
       connectorConnection);
 
     Object connectorJob = ClassUtils.instantiate(
       connector.getJobConfigurationClass(job.getType()));
-    FormUtils.fillValues(job.getConnectorPart().getForms(), connectorJob);
+    FormUtils.fromForms(job.getConnectorPart().getForms(), connectorJob);
 
     // Transform framework specific forms
     Object frameworkConnection = ClassUtils.instantiate(
       getConnectionConfigurationClass());
-    FormUtils.fillValues(connection.getFrameworkPart().getForms(),
+    FormUtils.fromForms(connection.getFrameworkPart().getForms(),
       frameworkConnection);
 
     Object frameworkJob = ClassUtils.instantiate(
       getJobConfigurationClass(job.getType()));
-    FormUtils.fillValues(job.getFrameworkPart().getForms(), frameworkJob);
+    FormUtils.fromForms(job.getFrameworkPart().getForms(), frameworkJob);
 
     // Create request object
     MSubmission summary = new MSubmission(jobId);
@@ -411,7 +411,7 @@ public final class FrameworkManager {
     ImportJobConfiguration jobConfiguration = (ImportJobConfiguration) request.getConfigFrameworkJob();
 
     // Initialize the map-reduce part (all sort of required classes, ...)
-    request.setOutputDirectory(jobConfiguration.outputDirectory);
+    request.setOutputDirectory(jobConfiguration.output.outputDirectory);
 
     // Delegate rest of the job to execution engine
     executionEngine.prepareImportSubmission(request);

http://git-wip-us.apache.org/repos/asf/sqoop/blob/211c6781/core/src/main/java/org/apache/sqoop/framework/configuration/ConnectionConfiguration.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/sqoop/framework/configuration/ConnectionConfiguration.java b/core/src/main/java/org/apache/sqoop/framework/configuration/ConnectionConfiguration.java
index bcf4dad..830606a 100644
--- a/core/src/main/java/org/apache/sqoop/framework/configuration/ConnectionConfiguration.java
+++ b/core/src/main/java/org/apache/sqoop/framework/configuration/ConnectionConfiguration.java
@@ -17,17 +17,14 @@
  */
 package org.apache.sqoop.framework.configuration;
 
-import org.apache.sqoop.model.Configuration;
-import org.apache.sqoop.model.Input;
-
-import static org.apache.sqoop.framework.FrameworkConstants.*;
+import org.apache.sqoop.model.ConfigurationClass;
+import org.apache.sqoop.model.Form;
 
 /**
  * Framework class representing connection configuration
  */
-@Configuration
+@ConfigurationClass
 public class ConnectionConfiguration {
 
-  @Input(form = FORM_SECURITY)
-  public Integer maxConnections;
+  @Form SecurityForm security;
 }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/211c6781/core/src/main/java/org/apache/sqoop/framework/configuration/ExportJobConfiguration.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/sqoop/framework/configuration/ExportJobConfiguration.java b/core/src/main/java/org/apache/sqoop/framework/configuration/ExportJobConfiguration.java
index 90541e9..330aff0 100644
--- a/core/src/main/java/org/apache/sqoop/framework/configuration/ExportJobConfiguration.java
+++ b/core/src/main/java/org/apache/sqoop/framework/configuration/ExportJobConfiguration.java
@@ -17,17 +17,14 @@
  */
 package org.apache.sqoop.framework.configuration;
 
-import org.apache.sqoop.model.Configuration;
-import org.apache.sqoop.model.Input;
-
-import static org.apache.sqoop.framework.FrameworkConstants.*;
+import org.apache.sqoop.model.ConfigurationClass;
+import org.apache.sqoop.model.Form;
 
 /**
  *
  */
-@Configuration
+@ConfigurationClass
 public class ExportJobConfiguration {
 
-  @Input(form = FORM_OUTPUT, size = 25)
-  public String ignored;
+  @Form OutputForm output;
 }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/211c6781/core/src/main/java/org/apache/sqoop/framework/configuration/ImportJobConfiguration.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/sqoop/framework/configuration/ImportJobConfiguration.java b/core/src/main/java/org/apache/sqoop/framework/configuration/ImportJobConfiguration.java
index d811593..8c4dcf1 100644
--- a/core/src/main/java/org/apache/sqoop/framework/configuration/ImportJobConfiguration.java
+++ b/core/src/main/java/org/apache/sqoop/framework/configuration/ImportJobConfiguration.java
@@ -17,20 +17,14 @@
  */
 package org.apache.sqoop.framework.configuration;
 
-import org.apache.sqoop.model.Configuration;
-import org.apache.sqoop.model.Input;
-
-import static org.apache.sqoop.framework.FrameworkConstants.*;
+import org.apache.sqoop.model.ConfigurationClass;
+import org.apache.sqoop.model.Form;
 
 /**
  *
  */
-@Configuration
+@ConfigurationClass
 public class ImportJobConfiguration {
 
-  @Input(form = FORM_OUTPUT, size = 25)
-  public StorageType storageType;
-
-  @Input(form = FORM_OUTPUT, size = 25)
-  public String outputDirectory;
+  @Form public OutputForm output;
 }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/211c6781/core/src/main/java/org/apache/sqoop/framework/configuration/OutputForm.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/sqoop/framework/configuration/OutputForm.java b/core/src/main/java/org/apache/sqoop/framework/configuration/OutputForm.java
new file mode 100644
index 0000000..3f70b5f
--- /dev/null
+++ b/core/src/main/java/org/apache/sqoop/framework/configuration/OutputForm.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.framework.configuration;
+
+import org.apache.sqoop.model.FormClass;
+import org.apache.sqoop.model.Input;
+
+/**
+ *
+ */
+@FormClass
+public class OutputForm {
+
+  @Input public StorageType storageType;
+
+  @Input(size = 25) public String outputDirectory;
+}

http://git-wip-us.apache.org/repos/asf/sqoop/blob/211c6781/core/src/main/java/org/apache/sqoop/framework/configuration/SecurityForm.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/sqoop/framework/configuration/SecurityForm.java b/core/src/main/java/org/apache/sqoop/framework/configuration/SecurityForm.java
new file mode 100644
index 0000000..8ab50ed
--- /dev/null
+++ b/core/src/main/java/org/apache/sqoop/framework/configuration/SecurityForm.java
@@ -0,0 +1,29 @@
+/**
+ * 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.framework.configuration;
+
+import org.apache.sqoop.model.FormClass;
+import org.apache.sqoop.model.Input;
+
+/**
+ * Security form
+ */
+@FormClass
+public class SecurityForm {
+  @Input public Integer maxConnections;
+}

http://git-wip-us.apache.org/repos/asf/sqoop/blob/211c6781/core/src/main/resources/framework-resources.properties
----------------------------------------------------------------------
diff --git a/core/src/main/resources/framework-resources.properties b/core/src/main/resources/framework-resources.properties
index 872f48e..5ddf32d 100644
--- a/core/src/main/resources/framework-resources.properties
+++ b/core/src/main/resources/framework-resources.properties
@@ -18,26 +18,26 @@
 ############################
 # Security Form
 #
-form-security-label = Security related configuration options
-form-security-help = You must supply the information requested in order to \
+security.label = Security related configuration options
+security.help = You must supply the information requested in order to \
                    create a job object.
 
-maxConnections-label = Max connections
-maxConnections-help = Maximal number of connections that this \
+security.maxConnections.label = Max connections
+security.maxConnections.help = Maximal number of connections that this \
                       connection object can use at one point in time
 
 # Output From
 #
-form-output-label = Output configuration
-form-output-help = You must supply the information requested in order to \
+output.label = Output configuration
+output.help = You must supply the information requested in order to \
                    get information where you want to store your data.
 
-storageType-label = Storage type
-storageType-help = Target on Hadoop ecosystem where to store data
+output.storageType.label = Storage type
+output.storageType.help = Target on Hadoop ecosystem where to store data
 
-outputDirectory-label = Output directory
-outputDirectory-help = Output directory for final data
+output.outputDirectory.label = Output directory
+output.outputDirectory.help = Output directory for final data
 
-ignored-label = Ignored
-ignored-help = This value is ignored
+output.ignored.label = Ignored
+output.ignored.help = This value is ignored
 

http://git-wip-us.apache.org/repos/asf/sqoop/blob/211c6781/server/src/main/java/org/apache/sqoop/handler/ConnectionRequestHandler.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/sqoop/handler/ConnectionRequestHandler.java b/server/src/main/java/org/apache/sqoop/handler/ConnectionRequestHandler.java
index 64ef84a..b77c5d7 100644
--- a/server/src/main/java/org/apache/sqoop/handler/ConnectionRequestHandler.java
+++ b/server/src/main/java/org/apache/sqoop/handler/ConnectionRequestHandler.java
@@ -163,9 +163,9 @@ public class ConnectionRequestHandler implements RequestHandler {
     Object frameworkConfig = ClassUtils.instantiate(
       FrameworkManager.getConnectionConfigurationClass());
 
-    FormUtils.fillValues(
+    FormUtils.fromForms(
       connection.getConnectorPart().getForms(), connectorConfig);
-    FormUtils.fillValues(
+    FormUtils.fromForms(
       connection.getFrameworkPart().getForms(), frameworkConfig);
 
     // Validate both parts

http://git-wip-us.apache.org/repos/asf/sqoop/blob/211c6781/server/src/main/java/org/apache/sqoop/handler/JobRequestHandler.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/sqoop/handler/JobRequestHandler.java b/server/src/main/java/org/apache/sqoop/handler/JobRequestHandler.java
index 070b290..6dea45f 100644
--- a/server/src/main/java/org/apache/sqoop/handler/JobRequestHandler.java
+++ b/server/src/main/java/org/apache/sqoop/handler/JobRequestHandler.java
@@ -164,8 +164,8 @@ public class JobRequestHandler implements RequestHandler {
     Object frameworkConfig = ClassUtils.instantiate(
       FrameworkManager.getJobConfigurationClass(job.getType()));
 
-    FormUtils.fillValues(job.getConnectorPart().getForms(), connectorConfig);
-    FormUtils.fillValues(job.getFrameworkPart().getForms(), frameworkConfig);
+    FormUtils.fromForms(job.getConnectorPart().getForms(), connectorConfig);
+    FormUtils.fromForms(job.getFrameworkPart().getForms(), frameworkConfig);
 
     // Validate both parts
     Validation connectorValidation =


Mime
View raw message