You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sqoop.apache.org by bl...@apache.org on 2012/10/17 20:50:47 UTC

[3/4] git commit: SQOOP-627: Convert forms structures on connector level to configuration classes (Jarek Jarcec Cecho)

SQOOP-627: Convert forms structures on connector level to configuration classes
(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/a46b25f5
Tree: http://git-wip-us.apache.org/repos/asf/sqoop/tree/a46b25f5
Diff: http://git-wip-us.apache.org/repos/asf/sqoop/diff/a46b25f5

Branch: refs/heads/sqoop2
Commit: a46b25f5e530151da592823982656a546ba6d1dc
Parents: 27aa786
Author: Bilung Lee <bl...@apache.org>
Authored: Wed Oct 17 09:23:39 2012 -0700
Committer: Bilung Lee <bl...@apache.org>
Committed: Wed Oct 17 09:23:39 2012 -0700

----------------------------------------------------------------------
 .../org/apache/sqoop/client/core/RequestCache.java |  199 +++++++
 .../sqoop/client/request/ConnectionRequest.java    |   15 +-
 .../apache/sqoop/client/request/JobRequest.java    |   15 +-
 .../client/shell/CloneConnectionFunction.java      |   25 +-
 .../sqoop/client/shell/CloneJobFunction.java       |   22 +-
 .../client/shell/CreateConnectionFunction.java     |   37 +--
 .../sqoop/client/shell/CreateJobFunction.java      |   53 +--
 .../client/shell/DeleteConnectionFunction.java     |   12 +-
 .../sqoop/client/shell/DeleteJobFunction.java      |    6 +-
 .../sqoop/client/shell/ShowConnectionFunction.java |   10 +-
 .../sqoop/client/shell/ShowConnectorFunction.java  |   10 +-
 .../sqoop/client/shell/ShowFrameworkFunction.java  |   11 +-
 .../apache/sqoop/client/shell/ShowJobFunction.java |    9 +-
 .../client/shell/UpdateConnectionFunction.java     |   21 +-
 .../sqoop/client/shell/UpdateJobFunction.java      |   23 +-
 .../org/apache/sqoop/client/utils/FormFiller.java  |    6 +-
 .../apache/sqoop/client/utils/FormFiller.java.orig |  432 +++++++++++++++
 .../java/org/apache/sqoop/json/ValidationBean.java |  196 +++-----
 .../java/org/apache/sqoop/model/Configuration.java |   30 +
 .../java/org/apache/sqoop/model/FormUtils.java     |  201 +++++++
 .../main/java/org/apache/sqoop/model/Input.java    |   50 ++
 .../org/apache/sqoop/model/MValidatedElement.java  |   52 +--
 .../java/org/apache/sqoop/model/ModelError.java    |   10 +
 .../org/apache/sqoop/utils/ClassLoadingUtils.java  |   34 ++
 .../java/org/apache/sqoop/validation/Status.java   |    9 +
 .../org/apache/sqoop/validation/Validation.java    |  124 ++++
 .../apache/sqoop/validation/ValidationError.java   |   48 ++
 .../org/apache/sqoop/json/TestValidationBean.java  |   75 ++-
 .../java/org/apache/sqoop/model/TestFormUtils.java |  174 ++++++
 .../apache/sqoop/utils/TestClassLoadingUtils.java  |   68 +++
 .../sqoop/connector/jdbc/GenericJdbcConnector.java |   80 +---
 .../sqoop/connector/jdbc/GenericJdbcValidator.java |   46 +--
 .../configuration/ConnectionConfiguration.java     |   48 ++
 .../jdbc/configuration/ExportJobConfiguration.java |   27 +
 .../jdbc/configuration/ImportJobConfiguration.java |   27 +
 .../generic-jdbc-connector-resources.properties    |   48 +-
 .../src/main/resources/sqoopconnector.properties   |    4 +-
 connector/pom.xml                                  |    2 +
 .../apache/sqoop/connector/ConnectorHandler.java   |   19 +-
 .../apache/sqoop/framework/FrameworkManager.java   |   71 +--
 .../configuration/ConnectionConfiguration.java     |   33 ++
 .../configuration/ExportJobConfiguration.java      |   33 ++
 .../configuration/ImportJobConfiguration.java      |   33 ++
 .../main/resources/framework-resources.properties  |   10 +-
 server/pom.xml                                     |    2 +
 .../sqoop/handler/ConnectionRequestHandler.java    |   46 ++-
 .../apache/sqoop/handler/JobRequestHandler.java    |   43 ++-
 .../apache/sqoop/connector/spi/SqoopConnector.java |   12 +-
 .../org/apache/sqoop/validation/Validator.java     |   83 +---
 49 files changed, 1964 insertions(+), 680 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/sqoop/blob/a46b25f5/client/src/main/java/org/apache/sqoop/client/core/RequestCache.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/sqoop/client/core/RequestCache.java b/client/src/main/java/org/apache/sqoop/client/core/RequestCache.java
new file mode 100644
index 0000000..03b1eb0
--- /dev/null
+++ b/client/src/main/java/org/apache/sqoop/client/core/RequestCache.java
@@ -0,0 +1,199 @@
+/**
+ * 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.client.core;
+
+import org.apache.sqoop.client.request.ConnectionRequest;
+import org.apache.sqoop.client.request.ConnectorRequest;
+import org.apache.sqoop.client.request.FrameworkRequest;
+import org.apache.sqoop.client.request.JobRequest;
+import org.apache.sqoop.json.ConnectionBean;
+import org.apache.sqoop.json.ConnectorBean;
+import org.apache.sqoop.json.FrameworkBean;
+import org.apache.sqoop.json.JobBean;
+import org.apache.sqoop.json.ValidationBean;
+import org.apache.sqoop.model.FormUtils;
+import org.apache.sqoop.model.MConnection;
+import org.apache.sqoop.model.MJob;
+import org.apache.sqoop.validation.Status;
+import org.apache.sqoop.validation.Validation;
+
+/**
+ *  Client wise caching of various request objects
+ */
+public final class RequestCache {
+
+  private static FrameworkRequest frameworkRequest;
+  private static ConnectorRequest connectorRequest;
+  private static ConnectionRequest connectionRequest;
+  private static JobRequest jobRequest;
+
+  public static FrameworkRequest getFrameworkRequest() {
+    if (frameworkRequest == null) {
+      frameworkRequest = new FrameworkRequest();
+    }
+
+    return frameworkRequest;
+  }
+
+  public static ConnectorRequest getConnectorRequest() {
+    if (connectorRequest == null) {
+      connectorRequest = new ConnectorRequest();
+    }
+
+    return connectorRequest;
+  }
+
+  public static ConnectionRequest getConnectionRequest() {
+    if (connectionRequest == null) {
+      connectionRequest = new ConnectionRequest();
+    }
+
+    return connectionRequest;
+  }
+
+  public static JobRequest getJobRequest() {
+    if (jobRequest == null) {
+      jobRequest = new JobRequest();
+    }
+
+    return jobRequest;
+  }
+
+  public static FrameworkBean readFramework() {
+    return getFrameworkRequest().read(Environment.getServerUrl());
+  }
+
+  public static ConnectorBean readConnector(String cid) {
+    return getConnectorRequest().read(Environment.getServerUrl(), cid);
+  }
+
+  public static ValidationBean createConnection(MConnection connection) {
+    return getConnectionRequest()
+      .create(Environment.getServerUrl(), connection);
+  }
+
+  public static Status createConnectionApplyValidations(MConnection connection) {
+    ValidationBean bean = createConnection(connection);
+
+    Validation connector = bean.getConnectorValidation();
+    Validation framework = bean.getFrameworkValidation();
+
+    FormUtils.applyValidation(connection.getConnectorPart().getForms(),
+      connector);
+    FormUtils.applyValidation(connection.getFrameworkPart().getForms(),
+      connector);
+
+    Long id = bean.getId();
+    if(id != null) {
+      connection.setPersistenceId(id);
+    }
+
+    return Status.getWorstStatus(connector.getStatus(), framework.getStatus());
+  }
+
+  public static ConnectionBean readConnection(String connectionId) {
+    return getConnectionRequest()
+      .read(Environment.getServerUrl(), connectionId);
+  }
+
+  public static ValidationBean updateConnection(MConnection connection) {
+    return getConnectionRequest()
+      .update(Environment.getServerUrl(), connection);
+  }
+
+  public static Status updateConnectionApplyValidations(MConnection connection){
+    ValidationBean bean = updateConnection(connection);
+
+    Validation connector = bean.getConnectorValidation();
+    Validation framework = bean.getFrameworkValidation();
+
+    FormUtils.applyValidation(connection.getConnectorPart().getForms(),
+      connector);
+    FormUtils.applyValidation(connection.getFrameworkPart().getForms(),
+      connector);
+
+    Long id = bean.getId();
+    if(id != null) {
+      connection.setPersistenceId(id);
+    }
+
+    return Status.getWorstStatus(connector.getStatus(), framework.getStatus());
+  }
+
+  public static void deleteConnection(String xid) {
+    getConnectionRequest().delete(Environment.getServerUrl(), xid);
+  }
+
+  public static ValidationBean createJob(MJob job) {
+    return getJobRequest().create(Environment.getServerUrl(), job);
+  }
+
+  public static Status createJobApplyValidations(MJob job) {
+    ValidationBean bean = createJob(job);
+
+    Validation connector = bean.getConnectorValidation();
+    Validation framework = bean.getFrameworkValidation();
+
+    FormUtils.applyValidation(job.getConnectorPart().getForms(),
+      connector);
+    FormUtils.applyValidation(job.getFrameworkPart().getForms(),
+      connector);
+
+    Long id = bean.getId();
+    if(id != null) {
+      job.setPersistenceId(id);
+    }
+
+    return Status.getWorstStatus(connector.getStatus(), framework.getStatus());
+  }
+
+  public static JobBean readJob(String jobId) {
+    return getJobRequest().read(Environment.getServerUrl(), jobId);
+  }
+
+  public static ValidationBean updateJob(MJob job) {
+    return getJobRequest().update(Environment.getServerUrl(), job);
+  }
+
+  public static Status updateJobApplyValidations(MJob job) {
+    ValidationBean bean = updateJob(job);
+
+    Validation connector = bean.getConnectorValidation();
+    Validation framework = bean.getFrameworkValidation();
+
+    FormUtils.applyValidation(job.getConnectorPart().getForms(),
+      connector);
+    FormUtils.applyValidation(job.getFrameworkPart().getForms(),
+      connector);
+
+    Long id = bean.getId();
+    if(id != null) {
+      job.setPersistenceId(id);
+    }
+
+    return Status.getWorstStatus(connector.getStatus(), framework.getStatus());
+  }
+
+  public static void deleteJob(String jid) {
+    getJobRequest().delete(Environment.getServerUrl(), jid);
+  }
+
+  private RequestCache() {
+    // Instantiation is prohibited
+  }
+}

http://git-wip-us.apache.org/repos/asf/sqoop/blob/a46b25f5/client/src/main/java/org/apache/sqoop/client/request/ConnectionRequest.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/sqoop/client/request/ConnectionRequest.java b/client/src/main/java/org/apache/sqoop/client/request/ConnectionRequest.java
index 80a84cd..f1e4d68 100644
--- a/client/src/main/java/org/apache/sqoop/client/request/ConnectionRequest.java
+++ b/client/src/main/java/org/apache/sqoop/client/request/ConnectionRequest.java
@@ -20,7 +20,6 @@ package org.apache.sqoop.client.request;
 import org.apache.sqoop.json.ConnectionBean;
 import org.apache.sqoop.json.ValidationBean;
 import org.apache.sqoop.model.MConnection;
-import org.apache.sqoop.validation.Status;
 import org.json.simple.JSONObject;
 import org.json.simple.JSONValue;
 
@@ -47,7 +46,7 @@ public class ConnectionRequest extends Request {
     return connectionBean;
   }
 
-  public Status create(String serverUrl, MConnection connection) {
+  public ValidationBean create(String serverUrl, MConnection connection) {
 
     ConnectionBean connectionBean = new ConnectionBean(connection);
     JSONObject connectionJson = connectionBean.extract();
@@ -55,13 +54,13 @@ public class ConnectionRequest extends Request {
     String response = super.post(serverUrl + RESOURCE,
                                  connectionJson.toJSONString());
 
-    ValidationBean validationBean = new ValidationBean(connection);
+    ValidationBean validationBean = new ValidationBean();
     validationBean.restore((JSONObject) JSONValue.parse(response));
 
-    return validationBean.getStatus();
+    return validationBean;
   }
 
-  public Status update(String serverUrl, MConnection connection) {
+  public ValidationBean update(String serverUrl, MConnection connection) {
 
     ConnectionBean connectionBean = new ConnectionBean(connection);
     JSONObject connectionJson = connectionBean.extract();
@@ -70,13 +69,13 @@ public class ConnectionRequest extends Request {
                                   + connection.getPersistenceId(),
                                 connectionJson.toJSONString());
 
-    ValidationBean validationBean = new ValidationBean(connection);
+    ValidationBean validationBean = new ValidationBean();
     validationBean.restore((JSONObject) JSONValue.parse(response));
 
-    return validationBean.getStatus();
+    return validationBean;
   }
 
-  public void delete(String serverUrl, long id) {
+  public void delete(String serverUrl, String id) {
      super.delete(serverUrl + RESOURCE + id);
   }
 }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/a46b25f5/client/src/main/java/org/apache/sqoop/client/request/JobRequest.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/sqoop/client/request/JobRequest.java b/client/src/main/java/org/apache/sqoop/client/request/JobRequest.java
index b93e407..c2449f5 100644
--- a/client/src/main/java/org/apache/sqoop/client/request/JobRequest.java
+++ b/client/src/main/java/org/apache/sqoop/client/request/JobRequest.java
@@ -20,7 +20,6 @@ package org.apache.sqoop.client.request;
 import org.apache.sqoop.json.JobBean;
 import org.apache.sqoop.json.ValidationBean;
 import org.apache.sqoop.model.MJob;
-import org.apache.sqoop.validation.Status;
 import org.json.simple.JSONObject;
 import org.json.simple.JSONValue;
 
@@ -47,7 +46,7 @@ public class JobRequest extends Request {
     return jobBean;
   }
 
-  public Status create(String serverUrl, MJob job) {
+  public ValidationBean create(String serverUrl, MJob job) {
 
     JobBean jobBean = new JobBean(job);
     JSONObject jobJson = jobBean.extract();
@@ -55,13 +54,13 @@ public class JobRequest extends Request {
     String response = super.post(serverUrl + RESOURCE,
       jobJson.toJSONString());
 
-    ValidationBean validationBean = new ValidationBean(job);
+    ValidationBean validationBean = new ValidationBean();
     validationBean.restore((JSONObject) JSONValue.parse(response));
 
-    return validationBean.getStatus();
+    return validationBean;
   }
 
-  public Status update(String serverUrl, MJob job) {
+  public ValidationBean update(String serverUrl, MJob job) {
 
     JobBean jobBean = new JobBean(job);
     JSONObject jobJson = jobBean.extract();
@@ -69,13 +68,13 @@ public class JobRequest extends Request {
     String response = super.put(serverUrl + RESOURCE + job.getPersistenceId(),
                                 jobJson.toJSONString());
 
-    ValidationBean validationBean = new ValidationBean(job);
+    ValidationBean validationBean = new ValidationBean();
     validationBean.restore((JSONObject) JSONValue.parse(response));
 
-    return validationBean.getStatus();
+    return validationBean;
   }
 
-  public void delete(String serverUrl, long id) {
+  public void delete(String serverUrl, String id) {
      super.delete(serverUrl + RESOURCE + id);
   }
 }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/a46b25f5/client/src/main/java/org/apache/sqoop/client/shell/CloneConnectionFunction.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/sqoop/client/shell/CloneConnectionFunction.java b/client/src/main/java/org/apache/sqoop/client/shell/CloneConnectionFunction.java
index eac23c6..21c41aa 100644
--- a/client/src/main/java/org/apache/sqoop/client/shell/CloneConnectionFunction.java
+++ b/client/src/main/java/org/apache/sqoop/client/shell/CloneConnectionFunction.java
@@ -21,8 +21,6 @@ import jline.ConsoleReader;
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.OptionBuilder;
 import org.apache.sqoop.client.core.ClientError;
-import org.apache.sqoop.client.core.Environment;
-import org.apache.sqoop.client.request.ConnectionRequest;
 import org.apache.sqoop.common.SqoopException;
 import org.apache.sqoop.json.ConnectionBean;
 import org.apache.sqoop.model.MConnection;
@@ -35,6 +33,7 @@ import java.util.List;
 import java.util.ResourceBundle;
 
 import static org.apache.sqoop.client.utils.FormFiller.*;
+import static org.apache.sqoop.client.core.RequestCache.*;
 
 /**
  *
@@ -43,8 +42,6 @@ public class CloneConnectionFunction extends SqoopFunction {
 
   private static final String XID = "xid";
 
-  private ConnectionRequest connectionRequest;
-
   private IO io;
 
   @SuppressWarnings("static-access")
@@ -108,27 +105,11 @@ public class CloneConnectionFunction extends SqoopFunction {
         return;
       }
 
-      // Try to create
-      status = createConnection(connection);
+      status = createConnectionApplyValidations(connection);
+
     } while(!status.canProceed());
 
     io.out.println("Connection was successfully created with validation status "
       + status.name() + " and persistent id " + connection.getPersistenceId());
   }
-
-  private Status createConnection(MConnection connection) {
-    if (connectionRequest == null) {
-      connectionRequest = new ConnectionRequest();
-    }
-
-    return connectionRequest.create(Environment.getServerUrl(), connection);
-  }
-
-  private ConnectionBean readConnection(String connectionId) {
-    if (connectionRequest == null) {
-      connectionRequest = new ConnectionRequest();
-    }
-
-    return connectionRequest.read(Environment.getServerUrl(), connectionId);
-  }
 }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/a46b25f5/client/src/main/java/org/apache/sqoop/client/shell/CloneJobFunction.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/sqoop/client/shell/CloneJobFunction.java b/client/src/main/java/org/apache/sqoop/client/shell/CloneJobFunction.java
index 536b7f3..b0e8d90 100644
--- a/client/src/main/java/org/apache/sqoop/client/shell/CloneJobFunction.java
+++ b/client/src/main/java/org/apache/sqoop/client/shell/CloneJobFunction.java
@@ -21,8 +21,6 @@ import jline.ConsoleReader;
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.OptionBuilder;
 import org.apache.sqoop.client.core.ClientError;
-import org.apache.sqoop.client.core.Environment;
-import org.apache.sqoop.client.request.JobRequest;
 import org.apache.sqoop.common.SqoopException;
 import org.apache.sqoop.json.JobBean;
 import org.apache.sqoop.model.MJob;
@@ -35,6 +33,7 @@ import java.util.List;
 import java.util.ResourceBundle;
 
 import static org.apache.sqoop.client.utils.FormFiller.*;
+import static org.apache.sqoop.client.core.RequestCache.*;
 
 /**
  *
@@ -43,8 +42,6 @@ public class CloneJobFunction extends SqoopFunction {
 
   private static final String JID = "jid";
 
-  private JobRequest jobRequest;
-
   private IO io;
 
   @SuppressWarnings("static-access")
@@ -107,26 +104,11 @@ public class CloneJobFunction extends SqoopFunction {
       }
 
       // Try to create
-      status = createJob(job);
+      status = createJobApplyValidations(job);
     } while(!status.canProceed());
 
     io.out.println("Job was successfully created with validation status "
       + status.name() + " and persistent id " + job.getPersistenceId());
   }
 
-  private Status createJob(MJob job) {
-    if (jobRequest == null) {
-      jobRequest = new JobRequest();
-    }
-
-    return jobRequest.create(Environment.getServerUrl(), job);
-  }
-
-  private JobBean readJob(String jobId) {
-    if (jobRequest == null) {
-      jobRequest = new JobRequest();
-    }
-
-    return jobRequest.read(Environment.getServerUrl(), jobId);
-  }
 }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/a46b25f5/client/src/main/java/org/apache/sqoop/client/shell/CreateConnectionFunction.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/sqoop/client/shell/CreateConnectionFunction.java b/client/src/main/java/org/apache/sqoop/client/shell/CreateConnectionFunction.java
index f35ba5b..ea1e5d8 100644
--- a/client/src/main/java/org/apache/sqoop/client/shell/CreateConnectionFunction.java
+++ b/client/src/main/java/org/apache/sqoop/client/shell/CreateConnectionFunction.java
@@ -21,10 +21,6 @@ import jline.ConsoleReader;
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.OptionBuilder;
 import org.apache.sqoop.client.core.ClientError;
-import org.apache.sqoop.client.core.Environment;
-import org.apache.sqoop.client.request.ConnectionRequest;
-import org.apache.sqoop.client.request.ConnectorRequest;
-import org.apache.sqoop.client.request.FrameworkRequest;
 import org.apache.sqoop.common.SqoopException;
 import org.apache.sqoop.json.ConnectorBean;
 import org.apache.sqoop.json.FrameworkBean;
@@ -39,6 +35,7 @@ import java.util.List;
 import java.util.ResourceBundle;
 
 import static org.apache.sqoop.client.utils.FormFiller.*;
+import static org.apache.sqoop.client.core.RequestCache.*;
 
 /**
  *
@@ -47,10 +44,6 @@ public class CreateConnectionFunction extends SqoopFunction {
 
   private static final String CID = "cid";
 
-  private FrameworkRequest frameworkRequest;
-  private ConnectorRequest connectorRequest;
-  private ConnectionRequest connectionRequest;
-
   private IO io;
 
   @SuppressWarnings("static-access")
@@ -85,8 +78,8 @@ public class CreateConnectionFunction extends SqoopFunction {
 
     ConsoleReader reader = new ConsoleReader();
 
-    FrameworkBean frameworkBean = getFrameworkBean();
-    ConnectorBean connectorBean = getConnectorBean(connectorId);
+    FrameworkBean frameworkBean = readFramework();
+    ConnectorBean connectorBean = readConnector(connectorId);
 
     MFramework framework = frameworkBean.getFramework();
     ResourceBundle frameworkBundle = frameworkBean.getResourceBundle();
@@ -116,7 +109,7 @@ public class CreateConnectionFunction extends SqoopFunction {
       }
 
       // Try to create
-      status = createConnection(connection);
+      status = createConnectionApplyValidations(connection);
     } while(!status.canProceed());
 
     io.out.println("New connection was successfully created with validation "
@@ -124,27 +117,5 @@ public class CreateConnectionFunction extends SqoopFunction {
       + connection.getPersistenceId());
   }
 
-  private FrameworkBean getFrameworkBean() {
-    if (frameworkRequest == null) {
-      frameworkRequest = new FrameworkRequest();
-    }
-
-    return frameworkRequest.read(Environment.getServerUrl());
-  }
-
-  private ConnectorBean getConnectorBean(String cid) {
-    if (connectorRequest == null) {
-      connectorRequest = new ConnectorRequest();
-    }
 
-    return connectorRequest.read(Environment.getServerUrl(), cid);
-  }
-
-  private Status createConnection(MConnection connection) {
-    if (connectionRequest == null) {
-      connectionRequest = new ConnectionRequest();
-    }
-
-    return connectionRequest.create(Environment.getServerUrl(), connection);
-  }
 }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/a46b25f5/client/src/main/java/org/apache/sqoop/client/shell/CreateJobFunction.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/sqoop/client/shell/CreateJobFunction.java b/client/src/main/java/org/apache/sqoop/client/shell/CreateJobFunction.java
index 41f43a3..0b685bf 100644
--- a/client/src/main/java/org/apache/sqoop/client/shell/CreateJobFunction.java
+++ b/client/src/main/java/org/apache/sqoop/client/shell/CreateJobFunction.java
@@ -21,11 +21,6 @@ import jline.ConsoleReader;
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.OptionBuilder;
 import org.apache.sqoop.client.core.ClientError;
-import org.apache.sqoop.client.core.Environment;
-import org.apache.sqoop.client.request.ConnectionRequest;
-import org.apache.sqoop.client.request.ConnectorRequest;
-import org.apache.sqoop.client.request.FrameworkRequest;
-import org.apache.sqoop.client.request.JobRequest;
 import org.apache.sqoop.common.SqoopException;
 import org.apache.sqoop.json.ConnectionBean;
 import org.apache.sqoop.json.ConnectorBean;
@@ -42,6 +37,7 @@ import java.util.List;
 import java.util.ResourceBundle;
 
 import static org.apache.sqoop.client.utils.FormFiller.*;
+import static org.apache.sqoop.client.core.RequestCache.*;
 
 /**
  * Handles creation of new job objects.
@@ -51,11 +47,6 @@ public class CreateJobFunction extends  SqoopFunction {
   private static final String XID = "xid";
   private static final String TYPE = "type";
 
-  private FrameworkRequest frameworkRequest;
-  private ConnectionRequest connectionRequest;
-  private ConnectorRequest connectorRequest;
-  private JobRequest jobRequest;
-
   private IO io;
 
   @SuppressWarnings("static-access")
@@ -101,8 +92,8 @@ public class CreateJobFunction extends  SqoopFunction {
 
     ConsoleReader reader = new ConsoleReader();
 
-    FrameworkBean frameworkBean = getFrameworkBean();
-    ConnectionBean connectionBean = getConnectionBean(connectionId);
+    FrameworkBean frameworkBean = readFramework();
+    ConnectionBean connectionBean = readConnection(connectionId);
     ConnectorBean connectorBean;
 
     MFramework framework = frameworkBean.getFramework();
@@ -110,7 +101,7 @@ public class CreateJobFunction extends  SqoopFunction {
 
     MConnection connection = connectionBean.getConnections().get(0);
 
-    connectorBean = getConnectorBean(connection.getConnectorId());
+    connectorBean = readConnector(String.valueOf(connection.getConnectorId()));
     MConnector connector = connectorBean.getConnectors().get(0);
     ResourceBundle connectorBundle = connectorBean.getResourceBundles().get(0);
 
@@ -141,45 +132,11 @@ public class CreateJobFunction extends  SqoopFunction {
       }
 
       // Try to create
-      status = createJob(job);
+      status = createJobApplyValidations(job);
     } while(!status.canProceed());
 
     io.out.println("New job was successfully created with validation "
       + "status " + status.name() + " and persistent id "
       + job.getPersistenceId());
   }
-
-
-  private FrameworkBean getFrameworkBean() {
-    if (frameworkRequest == null) {
-      frameworkRequest = new FrameworkRequest();
-    }
-
-    return frameworkRequest.read(Environment.getServerUrl());
-  }
-
-  private ConnectionBean getConnectionBean(String xid) {
-    if (connectionRequest == null) {
-      connectionRequest = new ConnectionRequest();
-    }
-
-    return connectionRequest.read(Environment.getServerUrl(), xid);
-  }
-
-  private ConnectorBean getConnectorBean(long cid) {
-    if (connectorRequest == null) {
-      connectorRequest = new ConnectorRequest();
-    }
-
-    return connectorRequest.read(Environment.getServerUrl(),
-      Long.toString(cid));
-  }
-
-  private Status createJob(MJob job) {
-    if (jobRequest == null) {
-      jobRequest = new JobRequest();
-    }
-
-    return jobRequest.create(Environment.getServerUrl(), job);
-  }
 }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/a46b25f5/client/src/main/java/org/apache/sqoop/client/shell/DeleteConnectionFunction.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/sqoop/client/shell/DeleteConnectionFunction.java b/client/src/main/java/org/apache/sqoop/client/shell/DeleteConnectionFunction.java
index 43a4002..ee2a1cf 100644
--- a/client/src/main/java/org/apache/sqoop/client/shell/DeleteConnectionFunction.java
+++ b/client/src/main/java/org/apache/sqoop/client/shell/DeleteConnectionFunction.java
@@ -19,11 +19,10 @@ package org.apache.sqoop.client.shell;
 
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.OptionBuilder;
-import org.apache.sqoop.client.core.Environment;
-import org.apache.sqoop.client.request.ConnectionRequest;
 import org.codehaus.groovy.tools.shell.IO;
 
 import java.util.List;
+import static org.apache.sqoop.client.core.RequestCache.*;
 
 /**
  *
@@ -32,8 +31,6 @@ public class DeleteConnectionFunction extends SqoopFunction {
 
   private IO io;
 
-  private ConnectionRequest connectionRequest;
-
   private static final String XID = "xid";
 
   @SuppressWarnings("static-access")
@@ -54,12 +51,7 @@ public class DeleteConnectionFunction extends SqoopFunction {
       return null;
     }
 
-    if (connectionRequest == null) {
-      connectionRequest = new ConnectionRequest();
-    }
-
-    connectionRequest.delete(Environment.getServerUrl(),
-                             Long.valueOf(line.getOptionValue(XID)));
+    deleteConnection(line.getOptionValue(XID));
 
     return null;
   }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/a46b25f5/client/src/main/java/org/apache/sqoop/client/shell/DeleteJobFunction.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/sqoop/client/shell/DeleteJobFunction.java b/client/src/main/java/org/apache/sqoop/client/shell/DeleteJobFunction.java
index 08f37d8..acc8e21 100644
--- a/client/src/main/java/org/apache/sqoop/client/shell/DeleteJobFunction.java
+++ b/client/src/main/java/org/apache/sqoop/client/shell/DeleteJobFunction.java
@@ -19,12 +19,13 @@ package org.apache.sqoop.client.shell;
 
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.OptionBuilder;
-import org.apache.sqoop.client.core.Environment;
 import org.apache.sqoop.client.request.JobRequest;
 import org.codehaus.groovy.tools.shell.IO;
 
 import java.util.List;
 
+import static org.apache.sqoop.client.core.RequestCache.*;
+
 /**
  * Handles deletion of a job object.
  */
@@ -58,8 +59,7 @@ public class DeleteJobFunction extends SqoopFunction {
       jobRequest = new JobRequest();
     }
 
-    jobRequest.delete(Environment.getServerUrl(),
-                      Long.valueOf(line.getOptionValue(JID)));
+    deleteJob(line.getOptionValue(JID));
 
     return null;
   }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/a46b25f5/client/src/main/java/org/apache/sqoop/client/shell/ShowConnectionFunction.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/sqoop/client/shell/ShowConnectionFunction.java b/client/src/main/java/org/apache/sqoop/client/shell/ShowConnectionFunction.java
index a499ff8..4e49288 100644
--- a/client/src/main/java/org/apache/sqoop/client/shell/ShowConnectionFunction.java
+++ b/client/src/main/java/org/apache/sqoop/client/shell/ShowConnectionFunction.java
@@ -19,8 +19,6 @@ package org.apache.sqoop.client.shell;
 
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.OptionBuilder;
-import org.apache.sqoop.client.core.Environment;
-import org.apache.sqoop.client.request.ConnectionRequest;
 import org.apache.sqoop.json.ConnectionBean;
 import org.apache.sqoop.model.MConnection;
 import org.codehaus.groovy.tools.shell.IO;
@@ -29,6 +27,7 @@ import java.io.PrintWriter;
 import java.util.List;
 
 import static org.apache.sqoop.client.utils.FormDisplayer.*;
+import static org.apache.sqoop.client.core.RequestCache.*;
 
 /**
  *
@@ -38,7 +37,6 @@ public class ShowConnectionFunction extends SqoopFunction {
   public static final String XID = "xid";
 
   private IO io;
-  private ConnectionRequest connectionRequest;
 
   @SuppressWarnings("static-access")
   protected ShowConnectionFunction(IO io) {
@@ -78,11 +76,7 @@ public class ShowConnectionFunction extends SqoopFunction {
   }
 
   private void showConnection(String xid) {
-    if (connectionRequest == null) {
-      connectionRequest = new ConnectionRequest();
-    }
-    ConnectionBean connectionBean =
-      connectionRequest.read(Environment.getServerUrl(), xid);
+    ConnectionBean connectionBean = readConnection(xid);
 
     List<MConnection> connections = connectionBean.getConnections();
 

http://git-wip-us.apache.org/repos/asf/sqoop/blob/a46b25f5/client/src/main/java/org/apache/sqoop/client/shell/ShowConnectorFunction.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/sqoop/client/shell/ShowConnectorFunction.java b/client/src/main/java/org/apache/sqoop/client/shell/ShowConnectorFunction.java
index 07c9c56..a34c48c 100644
--- a/client/src/main/java/org/apache/sqoop/client/shell/ShowConnectorFunction.java
+++ b/client/src/main/java/org/apache/sqoop/client/shell/ShowConnectorFunction.java
@@ -23,13 +23,12 @@ import java.util.ResourceBundle;
 
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.OptionBuilder;
-import org.apache.sqoop.client.core.Environment;
-import org.apache.sqoop.client.request.ConnectorRequest;
 import org.apache.sqoop.json.ConnectorBean;
 import org.apache.sqoop.model.MConnector;
 import org.codehaus.groovy.tools.shell.IO;
 
 import static org.apache.sqoop.client.utils.FormDisplayer.*;
+import static org.apache.sqoop.client.core.RequestCache.*;
 
 @SuppressWarnings("serial")
 public class ShowConnectorFunction extends SqoopFunction
@@ -38,7 +37,6 @@ public class ShowConnectorFunction extends SqoopFunction
   public static final String CID = "cid";
 
   private IO io;
-  private ConnectorRequest conntectorRequest;
 
   @SuppressWarnings("static-access")
   protected ShowConnectorFunction(IO io) {
@@ -78,11 +76,7 @@ public class ShowConnectorFunction extends SqoopFunction
   }
 
   private void showConnector(String cid) {
-    if (conntectorRequest == null) {
-      conntectorRequest = new ConnectorRequest();
-    }
-    ConnectorBean connectorBean =
-      conntectorRequest.read(Environment.getServerUrl(), cid);
+    ConnectorBean connectorBean = readConnector(cid);
     List<MConnector> connectors = connectorBean.getConnectors();
     List<ResourceBundle> bundles = connectorBean.getResourceBundles();
 

http://git-wip-us.apache.org/repos/asf/sqoop/blob/a46b25f5/client/src/main/java/org/apache/sqoop/client/shell/ShowFrameworkFunction.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/sqoop/client/shell/ShowFrameworkFunction.java b/client/src/main/java/org/apache/sqoop/client/shell/ShowFrameworkFunction.java
index 532ff04..8dcf976 100644
--- a/client/src/main/java/org/apache/sqoop/client/shell/ShowFrameworkFunction.java
+++ b/client/src/main/java/org/apache/sqoop/client/shell/ShowFrameworkFunction.java
@@ -17,8 +17,6 @@
  */
 package org.apache.sqoop.client.shell;
 
-import org.apache.sqoop.client.core.Environment;
-import org.apache.sqoop.client.request.FrameworkRequest;
 import org.apache.sqoop.json.FrameworkBean;
 import org.apache.sqoop.model.MFramework;
 import org.codehaus.groovy.tools.shell.IO;
@@ -28,6 +26,7 @@ import java.util.List;
 import java.util.ResourceBundle;
 
 import static org.apache.sqoop.client.utils.FormDisplayer.*;
+import static org.apache.sqoop.client.core.RequestCache.*;
 
 /**
  *
@@ -35,7 +34,6 @@ import static org.apache.sqoop.client.utils.FormDisplayer.*;
 public class ShowFrameworkFunction extends SqoopFunction {
 
   private IO io;
-  private FrameworkRequest frameworkRequest;
 
   @SuppressWarnings("static-access")
   protected ShowFrameworkFunction(IO io) {
@@ -60,12 +58,7 @@ public class ShowFrameworkFunction extends SqoopFunction {
   }
 
   private void showFramework() {
-    if (frameworkRequest == null) {
-      frameworkRequest = new FrameworkRequest();
-    }
-
-    FrameworkBean frameworkBean =
-      frameworkRequest.read(Environment.getServerUrl());
+    FrameworkBean frameworkBean = readFramework();
 
     MFramework framework = frameworkBean.getFramework();
     ResourceBundle bundle = frameworkBean.getResourceBundle();

http://git-wip-us.apache.org/repos/asf/sqoop/blob/a46b25f5/client/src/main/java/org/apache/sqoop/client/shell/ShowJobFunction.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/sqoop/client/shell/ShowJobFunction.java b/client/src/main/java/org/apache/sqoop/client/shell/ShowJobFunction.java
index 19b11cc..ee8c63d 100644
--- a/client/src/main/java/org/apache/sqoop/client/shell/ShowJobFunction.java
+++ b/client/src/main/java/org/apache/sqoop/client/shell/ShowJobFunction.java
@@ -19,8 +19,6 @@ package org.apache.sqoop.client.shell;
 
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.OptionBuilder;
-import org.apache.sqoop.client.core.Environment;
-import org.apache.sqoop.client.request.JobRequest;
 import org.apache.sqoop.json.JobBean;
 import org.apache.sqoop.model.MJob;
 import org.codehaus.groovy.tools.shell.IO;
@@ -29,6 +27,7 @@ import java.io.PrintWriter;
 import java.util.List;
 
 import static org.apache.sqoop.client.utils.FormDisplayer.*;
+import static org.apache.sqoop.client.core.RequestCache.*;
 
 /**
  *
@@ -39,7 +38,6 @@ public class ShowJobFunction extends SqoopFunction {
   public static final String JID = "jid";
 
   private IO io;
-  private JobRequest jobRequest;
 
   @SuppressWarnings("static-access")
   protected ShowJobFunction(IO io) {
@@ -79,10 +77,7 @@ public class ShowJobFunction extends SqoopFunction {
   }
 
   private void showJob(String jid) {
-    if (jobRequest == null) {
-      jobRequest = new JobRequest();
-    }
-    JobBean jobBean = jobRequest.read(Environment.getServerUrl(), jid);
+    JobBean jobBean = readJob(jid);
 
     List<MJob> jobs = jobBean.getJobs();
 

http://git-wip-us.apache.org/repos/asf/sqoop/blob/a46b25f5/client/src/main/java/org/apache/sqoop/client/shell/UpdateConnectionFunction.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/sqoop/client/shell/UpdateConnectionFunction.java b/client/src/main/java/org/apache/sqoop/client/shell/UpdateConnectionFunction.java
index 64604f1..4e55dba 100644
--- a/client/src/main/java/org/apache/sqoop/client/shell/UpdateConnectionFunction.java
+++ b/client/src/main/java/org/apache/sqoop/client/shell/UpdateConnectionFunction.java
@@ -21,8 +21,6 @@ import jline.ConsoleReader;
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.OptionBuilder;
 import org.apache.sqoop.client.core.ClientError;
-import org.apache.sqoop.client.core.Environment;
-import org.apache.sqoop.client.request.ConnectionRequest;
 import org.apache.sqoop.common.SqoopException;
 import org.apache.sqoop.json.ConnectionBean;
 import org.apache.sqoop.model.MConnection;
@@ -34,6 +32,7 @@ import java.util.List;
 import java.util.ResourceBundle;
 
 import static org.apache.sqoop.client.utils.FormFiller.*;
+import static org.apache.sqoop.client.core.RequestCache.*;
 
 /**
  *
@@ -42,8 +41,6 @@ public class UpdateConnectionFunction extends SqoopFunction {
 
   private static final String XID = "xid";
 
-  private ConnectionRequest connectionRequest;
-
   private IO io;
 
   @SuppressWarnings("static-access")
@@ -104,26 +101,12 @@ public class UpdateConnectionFunction extends SqoopFunction {
       }
 
       // Try to create
-      status = updateConnection(connection);
+      status = updateConnectionApplyValidations(connection);
     } while(!status.canProceed());
 
     io.out.println("Connection was successfully updated with status "
       + status.name());
   }
 
-  private Status updateConnection(MConnection connection) {
-    if (connectionRequest == null) {
-      connectionRequest = new ConnectionRequest();
-    }
-
-    return connectionRequest.update(Environment.getServerUrl(), connection);
-  }
 
-  private ConnectionBean readConnection(String connectionId) {
-    if (connectionRequest == null) {
-      connectionRequest = new ConnectionRequest();
-    }
-
-    return connectionRequest.read(Environment.getServerUrl(), connectionId);
-  }
 }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/a46b25f5/client/src/main/java/org/apache/sqoop/client/shell/UpdateJobFunction.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/sqoop/client/shell/UpdateJobFunction.java b/client/src/main/java/org/apache/sqoop/client/shell/UpdateJobFunction.java
index ee387fd..f7cdf26 100644
--- a/client/src/main/java/org/apache/sqoop/client/shell/UpdateJobFunction.java
+++ b/client/src/main/java/org/apache/sqoop/client/shell/UpdateJobFunction.java
@@ -21,8 +21,6 @@ import jline.ConsoleReader;
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.OptionBuilder;
 import org.apache.sqoop.client.core.ClientError;
-import org.apache.sqoop.client.core.Environment;
-import org.apache.sqoop.client.request.JobRequest;
 import org.apache.sqoop.common.SqoopException;
 import org.apache.sqoop.json.JobBean;
 import org.apache.sqoop.model.MJob;
@@ -34,6 +32,7 @@ import java.util.List;
 import java.util.ResourceBundle;
 
 import static org.apache.sqoop.client.utils.FormFiller.*;
+import static org.apache.sqoop.client.core.RequestCache.*;
 
 /**
  *
@@ -42,8 +41,6 @@ public class UpdateJobFunction extends SqoopFunction {
 
   private static final String JID = "jid";
 
-  private JobRequest jobRequest;
-
   private IO io;
 
   @SuppressWarnings("static-access")
@@ -103,26 +100,10 @@ public class UpdateJobFunction extends SqoopFunction {
       }
 
       // Try to create
-      status = updateJob(job);
+      status = updateJobApplyValidations(job);
     } while(!status.canProceed());
 
     io.out.println("Job was successfully updated with status "
       + status.name());
   }
-
-  private Status updateJob(MJob job) {
-    if (jobRequest == null) {
-      jobRequest = new JobRequest();
-    }
-
-    return jobRequest.update(Environment.getServerUrl(), job);
-  }
-
-  private JobBean readJob(String jobId) {
-    if (jobRequest == null) {
-      jobRequest = new JobRequest();
-    }
-
-    return jobRequest.read(Environment.getServerUrl(), jobId);
-  }
 }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/a46b25f5/client/src/main/java/org/apache/sqoop/client/utils/FormFiller.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/sqoop/client/utils/FormFiller.java b/client/src/main/java/org/apache/sqoop/client/utils/FormFiller.java
index d2fb6ce..55d1cc0 100644
--- a/client/src/main/java/org/apache/sqoop/client/utils/FormFiller.java
+++ b/client/src/main/java/org/apache/sqoop/client/utils/FormFiller.java
@@ -161,11 +161,11 @@ public final class FormFiller {
                                   ResourceBundle bundle) throws IOException {
     // Print out warning or error message in case some validations were already
     // performed.
-    switch (input.getValidationSeverity()) {
-      case ERROR:
+    switch (input.getValidationStatus()) {
+      case UNACCEPTABLE:
         errorMessage(io, input.getValidationMessage());
         break;
-      case WARNING:
+      case ACCEPTABLE:
         warningMessage(io, input.getValidationMessage());
         break;
       default:

http://git-wip-us.apache.org/repos/asf/sqoop/blob/a46b25f5/client/src/main/java/org/apache/sqoop/client/utils/FormFiller.java.orig
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/sqoop/client/utils/FormFiller.java.orig b/client/src/main/java/org/apache/sqoop/client/utils/FormFiller.java.orig
new file mode 100644
index 0000000..d2fb6ce
--- /dev/null
+++ b/client/src/main/java/org/apache/sqoop/client/utils/FormFiller.java.orig
@@ -0,0 +1,432 @@
+/**
+ * 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.client.utils;
+
+import jline.ConsoleReader;
+import org.apache.sqoop.client.core.Environment;
+import org.apache.sqoop.model.MConnection;
+import org.apache.sqoop.model.MForm;
+import org.apache.sqoop.model.MInput;
+import org.apache.sqoop.model.MIntegerInput;
+import org.apache.sqoop.model.MMapInput;
+import org.apache.sqoop.model.MJob;
+import org.apache.sqoop.model.MStringInput;
+import org.codehaus.groovy.tools.shell.IO;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.ResourceBundle;
+
+/**
+ * Convenient methods for retrieving user input.
+ */
+public final class FormFiller {
+
+  /**
+   * Internal input that will be reused for loading names for connection and
+   * job objects.
+   */
+  private static MStringInput nameInput =
+    new MStringInput("object-name", false, (short)25);
+
+  /**
+   * Fill job object based on user input.
+   *
+   * @param io Shell's io object
+   * @param reader Associated console reader object
+   * @param job Job that user is suppose to fill in
+   * @param connectorBundle Connector resource bundle
+   * @param frameworkBundle Framework resource bundle
+   * @return True if we filled all inputs, false if user has stopped processing
+   * @throws IOException
+   */
+  public static boolean fillJob(IO io,
+                                ConsoleReader reader,
+                                MJob job,
+                                ResourceBundle connectorBundle,
+                                ResourceBundle frameworkBundle)
+                                throws IOException {
+
+    job.setName(getName(io, reader, job.getName()));
+
+    // Fill in data from user
+     return fillForms(io,
+                      reader,
+                      job.getConnectorPart().getForms(),
+                      connectorBundle,
+                      job.getFrameworkPart().getForms(),
+                      frameworkBundle);
+  }
+
+  /**
+   * Fill connection object based on user input.
+   *
+   * @param io Shell's io object
+   * @param reader Associated console reader object
+   * @param connection Connection that user is suppose to fill in
+   * @param connectorBundle Connector resource bundle
+   * @param frameworkBundle Framework resouce bundle
+   * @return True if we filled all inputs, false if user has stopped processing
+   * @throws IOException
+   */
+  public static boolean fillConnection(IO io,
+                                       ConsoleReader reader,
+                                       MConnection connection,
+                                       ResourceBundle connectorBundle,
+                                       ResourceBundle frameworkBundle)
+                                       throws IOException {
+
+    connection.setName(getName(io, reader, connection.getName()));
+
+    // Fill in data from user
+     return fillForms(io,
+                      reader,
+                      connection.getConnectorPart().getForms(),
+                      connectorBundle,
+                      connection.getFrameworkPart().getForms(),
+                      frameworkBundle);
+  }
+
+  public static boolean fillForms(IO io,
+                                  ConsoleReader reader,
+                                  List<MForm> connectorForms,
+                                  ResourceBundle connectorBundle,
+                                  List<MForm> frameworkForms,
+                                  ResourceBundle frameworkBundle
+                                  ) throws IOException {
+
+
+    // Query connector forms
+    if(!fillForms(io, connectorForms, reader, connectorBundle)) {
+      return false;
+    }
+
+    // Query framework forms
+    if(!fillForms(io, frameworkForms, reader, frameworkBundle)) {
+      return false;
+    }
+
+    return true;
+  }
+
+  public static boolean fillForms(IO io,
+                                  List<MForm> forms,
+                                  ConsoleReader reader,
+                                  ResourceBundle bundle)
+    throws IOException {
+    for (MForm form : forms) {
+      if(!fillForm(io, form, reader, bundle)) {
+        return false;
+      }
+    }
+
+    return true;
+  }
+
+  public static boolean fillForm(IO io,
+                                 MForm form,
+                                 ConsoleReader reader,
+                                 ResourceBundle bundle) throws IOException {
+    io.out.println("");
+    io.out.println(bundle.getString(form.getLabelKey()));
+    for (MInput input : form.getInputs()) {
+      if(!fillInput(io, input, reader, bundle)) {
+        return false;
+      }
+    }
+
+    return true;
+  }
+
+  public static boolean fillInput(IO io,
+                                  MInput input,
+                                  ConsoleReader reader,
+                                  ResourceBundle bundle) throws IOException {
+    // Print out warning or error message in case some validations were already
+    // performed.
+    switch (input.getValidationSeverity()) {
+      case ERROR:
+        errorMessage(io, input.getValidationMessage());
+        break;
+      case WARNING:
+        warningMessage(io, input.getValidationMessage());
+        break;
+      default:
+        // Simply ignore all other states for the moment
+        break;
+    }
+
+    // Based on the input type, let's perform specific load
+    switch (input.getType()) {
+      case STRING:
+        return fillInputString(io, (MStringInput) input, reader, bundle);
+      case INTEGER:
+        return fillInputInteger(io, (MIntegerInput) input, reader, bundle);
+      case MAP:
+        return fillInputMap(io, (MMapInput)input, reader, bundle);
+      default:
+        io.out.println("Unsupported data type " + input.getType());
+        return true;
+    }
+  }
+
+  /**
+   * Load user input for map type.
+   *
+   * This implementation will load one map entry at the time. Current flows is
+   * as follows: if user did not enter anything (empty input) finish loading
+   * and return from function. If user specified input with equal sign (=),
+   * lets add new key value pair. Otherwise consider entire input as a key name
+   * and try to remove it from the map.
+   *
+   * Please note that following code do not supports equal sign in property
+   * name. It's however perfectly fine to have equal sign in value.
+   *
+   * @param io Shell's IO object
+   * @param input Input that we should read or edit
+   * @param reader Associated console reader
+   * @param bundle Resource bundle
+   * @return True if user wish to continue with loading additional inputs
+   * @throws IOException
+   */
+  private static boolean fillInputMap(IO io,
+                                      MMapInput input,
+                                      ConsoleReader reader,
+                                      ResourceBundle bundle)
+                                      throws IOException {
+    // Special prompt in Map case
+    io.out.println(bundle.getString(input.getLabelKey()) + ": ");
+
+    // Internal loading map
+    Map<String, String> values = input.getValue();
+    if(values == null) {
+      values = new HashMap<String, String>();
+    }
+
+    String userTyped;
+
+    while(true) {
+      // Print all current items in each iteration
+      io.out.println("There are currently " + values.size()
+        + " values in the map:");
+      for(Map.Entry<String, String> entry : values.entrySet()) {
+        io.out.println(entry.getKey() + " = " + entry.getValue());
+      }
+
+      // Special prompt for Map entry
+      reader.printString("entry# ");
+      reader.flushConsole();
+
+      userTyped = reader.readLine();
+
+      if(userTyped == null) {
+        // Finish loading and return back to Sqoop shell
+        return false;
+      } else if(userTyped.isEmpty()) {
+        // User has finished loading data to Map input, either set input empty
+        // if there are no entries or propagate entries to the input
+        if(values.size() == 0) {
+          input.setEmpty();
+        } else {
+          input.setValue(values);
+        }
+        return true;
+      } else {
+        // User has specified regular input, let's check if it contains equals
+        // sign. Save new entry (or update existing one) if it does. Otherwise
+        // try to remove entry that user specified.
+        if(userTyped.contains("=")) {
+          String []keyValue = userTyped.split("=", 2);
+          values.put(handleUserInput(keyValue[0]), handleUserInput(keyValue[1]));
+        } else {
+          String key = handleUserInput(userTyped);
+          if(values.containsKey(key)) {
+            values.remove(key);
+          } else {
+            errorMessage(io, "Don't know what to do with " + userTyped);
+          }
+        }
+      }
+
+    }
+  }
+
+  /**
+   * Handle special cases in user input.
+   *
+   * Preserve null and empty values, remove whitespace characters before and
+   * after loaded string and de-quote the string if it's quoted (to preserve
+   * spaces for example).
+   *
+   * @param input String loaded from user
+   * @return Unquoted transformed string
+   */
+  private static String handleUserInput(String input) {
+    // Preserve null and empty values
+    if(input == null) {
+      return null;
+    }
+    if(input.isEmpty()) {
+      return input;
+    }
+
+    // Removes empty characters at the begging and end of loaded string
+    input = input.trim();
+
+    int lastIndex = input.length() - 1;
+    char first = input.charAt(0);
+    char last = input.charAt(lastIndex);
+
+    // Remove quoting if present
+    if(first == '\'' && last == '\'') {
+      input = input.substring(1, lastIndex);
+    } else if(first == '"' && last == '"') {
+      input =  input.substring(1, lastIndex);
+    }
+
+    // Return final string
+    return input;
+  }
+
+  private static boolean fillInputInteger(IO io,
+                                          MIntegerInput input,
+                                          ConsoleReader reader,
+                                          ResourceBundle bundle)
+                                          throws IOException {
+    generatePrompt(reader, bundle, input);
+
+    // Fill already filled data when available
+    if(!input.isEmpty()) {
+      reader.putString(input.getValue().toString());
+    }
+
+    String userTyped = reader.readLine();
+
+    if (userTyped == null) {
+      return false;
+    } else if (userTyped.isEmpty()) {
+      input.setEmpty();
+    } else {
+      Integer value;
+      try {
+        value = Integer.valueOf(userTyped);
+        input.setValue(value);
+      } catch (NumberFormatException ex) {
+        errorMessage(io, "Input is not valid integer number");
+        return fillInputInteger(io, input, reader, bundle);
+      }
+
+      input.setValue(Integer.valueOf(userTyped));
+    }
+
+    return true;
+  }
+
+  /**
+   * Load string input from the user.
+   *
+   * @param io Shell's IO object
+   * @param input Input that we should load in
+   * @param reader Associated console reader
+   * @param bundle Resource bundle for this input
+   * @return
+   * @throws IOException
+   */
+  public static boolean fillInputString(IO io,
+                                        MStringInput input,
+                                        ConsoleReader reader,
+                                        ResourceBundle bundle)
+                                        throws IOException {
+    generatePrompt(reader, bundle, input);
+
+    // Fill already filled data when available
+    // However do not printout if this input contains sensitive information.
+    if(!input.isEmpty() && !input.isMasked()) {
+      reader.putString(input.getValue());
+    }
+
+    // Get the data
+    String userTyped;
+    if(input.isMasked()) {
+       userTyped = reader.readLine('*');
+    } else {
+      userTyped = reader.readLine();
+    }
+
+    if (userTyped == null) {
+      // Propagate end of loading process
+      return false;
+    } else if (userTyped.isEmpty()) {
+      // Empty input in case that nothing was given
+      input.setEmpty();
+    } else {
+      // Set value that user has entered
+      input.setValue(userTyped);
+
+      // Check that it did not exceeds maximal allowance for given input
+      if(userTyped.length() > input.getMaxLength()) {
+        errorMessage(io, "Size of input exceeds allowance for this input"
+          + " field. Maximal allowed size is " + input.getMaxLength());
+        return fillInputString(io, input, reader, bundle);
+      }
+    }
+
+    return true;
+  }
+
+  public static void generatePrompt(ConsoleReader reader,
+                                    ResourceBundle bundle,
+                                    MInput input)
+                                    throws IOException {
+    reader.printString(bundle.getString(input.getLabelKey()) + ": ");
+    reader.flushConsole();
+  }
+
+  public static String getName(IO io, ConsoleReader reader,
+                               String name) throws IOException {
+    if(name == null) {
+      nameInput.setEmpty();
+    } else {
+      nameInput.setValue(name);
+    }
+
+    fillInputString(io, nameInput, reader, Environment.getResourceBundle());
+
+    return nameInput.getValue();
+  }
+
+  public static void errorMessage(IO io, String message) {
+    io.out.println("Error message: @|red " + message + " |@");
+  }
+
+  public static void warningMessage(IO io, String message) {
+    io.out.println("Warning message: @|yellow " + message + " |@");
+  }
+
+  public static void errorIntroduction(IO io) {
+    io.out.println();
+    io.out.println("@|red There are issues with entered data, please"
+      + " revise your input:|@");
+  }
+
+  private FormFiller() {
+    // Do not instantiate
+  }
+}

http://git-wip-us.apache.org/repos/asf/sqoop/blob/a46b25f5/common/src/main/java/org/apache/sqoop/json/ValidationBean.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/json/ValidationBean.java b/common/src/main/java/org/apache/sqoop/json/ValidationBean.java
index 8b8de72..1ad8186 100644
--- a/common/src/main/java/org/apache/sqoop/json/ValidationBean.java
+++ b/common/src/main/java/org/apache/sqoop/json/ValidationBean.java
@@ -17,183 +17,127 @@
  */
 package org.apache.sqoop.json;
 
-import org.apache.sqoop.model.MConnection;
-import org.apache.sqoop.model.MForm;
-import org.apache.sqoop.model.MInput;
-import org.apache.sqoop.model.MJob;
-import org.apache.sqoop.model.MPersistableEntity;
-import org.apache.sqoop.model.MValidatedElement;
 import org.apache.sqoop.validation.Status;
+import org.apache.sqoop.validation.Validation;
 import org.json.simple.JSONObject;
 
-import java.util.List;
+import java.util.HashMap;
+import java.util.Map;
 
 /**
- * Bean for sending validations across network. As is expected that both filled
- * forms will be available on both ends (client and server), we're transferring
- * only validation status and messages.
+ * Bean for sending validations across network. This bean will move two
+ * validation objects at one time - one for connector and second for framework
+ * part of validated entity. Optionally validation bean can also transfer
+ * created persistent id in case that new entity was created.
  */
 public class ValidationBean implements JsonBean {
 
-  private static final String STATUS = "status";
-  private static final String TYPE = "type";
   private static final String ID = "id";
-  private static final String CONNECTOR_PART = "connector";
-  private static final String FRAMEWORK_PART = "framework";
-
-  private static final String SEVERITY = "severity";
+  private static final String FRAMEWORK = "framework";
+  private static final String CONNECTOR = "connector";
+  private static final String STATUS = "status";
   private static final String MESSAGE = "message";
+  private static final String MESSAGES = "messages";
 
-  private MConnection connection;
-  private MJob job;
-  private Status status;
+  private Long id;
+  private Validation connectorValidation;
+  private Validation frameworkValidation;
 
   // For "extract"
-  public ValidationBean(MConnection connection, Status status) {
-    this.connection = connection;
-    this.status = status;
-  }
-  public ValidationBean(MJob job, Status status) {
-    this.job = job;
-    this.status = status;
+  public ValidationBean(Validation connector, Validation framework) {
+    this();
+
+    this.connectorValidation = connector;
+    this.frameworkValidation = framework;
   }
 
   // For "restore"
-  public ValidationBean(MConnection connection) {
-    this.connection = connection;
+  public ValidationBean() {
+    id = null;
   }
-  public ValidationBean(MJob job) {
-    this.job = job;
+
+  public Validation getConnectorValidation() {
+    return connectorValidation;
   }
 
-  public MConnection getConnection() {
-    return connection;
+  public Validation getFrameworkValidation() {
+    return frameworkValidation;
   }
-  public MJob getJob() {
-    return job;
+
+  public void setId(Long id) {
+    this.id = id;
   }
 
-  public Status getStatus() {
-    return status;
+  public Long getId() {
+    return id;
   }
 
   @SuppressWarnings("unchecked")
-  @Override
   public JSONObject extract() {
     JSONObject object = new JSONObject();
 
-    List<MForm> connectorPart = null;
-    List<MForm> frameworkPart = null;
-
-    if(connection != null) {
-      connectorPart = connection.getConnectorPart().getForms();
-      frameworkPart = connection.getFrameworkPart().getForms();
-      object.put(TYPE, "CONNECTION");
-    } else if (job != null) {
-      connectorPart = job.getConnectorPart().getForms();
-      frameworkPart = job.getFrameworkPart().getForms();
-      object.put(TYPE, "FRAMEWORK");
-    } else {
-      // This should never happen
-      return null;
-    }
-
-
-    object.put(STATUS, status.name());
-    object.put(CONNECTOR_PART, extractForms(connectorPart));
-    object.put(FRAMEWORK_PART, extractForms(frameworkPart));
-
-    // If we do have ID available, let's send it across network
-    long id = MPersistableEntity.PERSISTANCE_ID_DEFAULT;
-    if(connection != null) {
-      id = connection.getPersistenceId();
-    } else if(job != null) {
-      id = job.getPersistenceId();
-    }
-    if( id != MPersistableEntity.PERSISTANCE_ID_DEFAULT) {
+    // Optionally transfer id
+    if(id != null) {
       object.put(ID, id);
     }
 
-    return object;
-  }
+    object.put(CONNECTOR, extractValidation(connectorValidation));
+    object.put(FRAMEWORK, extractValidation(frameworkValidation));
 
-  @SuppressWarnings("unchecked")
-  private JSONObject extractForms(List<MForm> forms) {
-    JSONObject ret = new JSONObject();
-
-    for (MForm form : forms) {
-      ret.put(form.getPersistenceId(), extractForm(form));
-    }
-    return ret;
+    return object;
   }
 
   @SuppressWarnings("unchecked")
-  private JSONObject extractForm(MForm form) {
+  private JSONObject extractValidation(Validation validation) {
     JSONObject object = new JSONObject();
 
-    for (MInput input : form.getInputs()) {
-      if (input.getValidationSeverity() != MValidatedElement.Severity.OK) {
-        JSONObject validation = new JSONObject();
-        validation.put(SEVERITY, input.getValidationSeverity().name());
-        validation.put(MESSAGE, input.getValidationMessage());
+    object.put(STATUS, validation.getStatus().name());
+
+    JSONObject jsonMessages = new JSONObject();
+    Map<String, Validation.Message> messages = validation.getMessages();
 
-        object.put(input.getPersistenceId(), validation);
-      }
+    for(Map.Entry<String, Validation.Message> entry : messages.entrySet()) {
+      JSONObject jsonEntry = new JSONObject();
+      jsonEntry.put(STATUS, entry.getValue().getStatus().name());
+      jsonEntry.put(MESSAGE, entry.getValue().getMessage());
+      jsonMessages.put(entry.getKey(), jsonEntry);
     }
 
+    object.put(MESSAGES, jsonMessages);
+
     return object;
   }
 
   @Override
   public void restore(JSONObject jsonObject) {
-    status = Status.valueOf((String) jsonObject.get(STATUS));
-
-    JSONObject connectorPart = (JSONObject) jsonObject.get(CONNECTOR_PART);
-    JSONObject frameworkPart = (JSONObject) jsonObject.get(FRAMEWORK_PART);
-
-    if(connection != null) {
-      restoreForms(connectorPart, connection.getConnectorPart().getForms());
-      restoreForms(frameworkPart, connection.getFrameworkPart().getForms());
-    } else if (job != null) {
-      restoreForms(connectorPart, job.getConnectorPart().getForms());
-      restoreForms(frameworkPart, job.getFrameworkPart().getForms());
-    }
+    // Optional and accepting NULLs
+    id = (Long) jsonObject.get(ID);
 
-    // Restore persistent id if available
-    if(jsonObject.containsKey(ID)) {
-      long id = (Long)jsonObject.get(ID);
-      if(connection != null) {
-        connection.setPersistenceId(id);
-      } else if(job != null) {
-        job.setPersistenceId(id);
-      }
-    }
+    connectorValidation = restoreValidation(
+      (JSONObject)jsonObject.get(CONNECTOR));
+    frameworkValidation = restoreValidation(
+      (JSONObject)jsonObject.get(FRAMEWORK));
   }
 
-  private void restoreForms(JSONObject json, List<MForm> forms) {
-    for (MForm form : forms) {
-      String id = Long.toString(form.getPersistenceId());
-      if (json.containsKey(id)) {
-        restoreForm((JSONObject) json.get(id), form);
-      }
-    }
-  }
+  public Validation restoreValidation(JSONObject jsonObject) {
+    JSONObject jsonMessages = (JSONObject) jsonObject.get(MESSAGES);
+    Map<String, Validation.Message> messages
+      = new HashMap<String, Validation.Message>();
+
+    for(Object key : jsonMessages.keySet()) {
+      JSONObject jsonMessage = (JSONObject) jsonMessages.get(key);
 
-  private void restoreForm(JSONObject json, MForm form) {
-    for (MInput input : form.getInputs()) {
-      String id = Long.toString(input.getPersistenceId());
-      if (json.containsKey(id)) {
-        JSONObject validation = (JSONObject) json.get(id);
+      Status status = Status.valueOf((String) jsonMessage.get(STATUS));
+      String stringMessage = (String) jsonMessage.get(MESSAGE);
 
-        MValidatedElement.Severity severity =
-          MValidatedElement.Severity.valueOf((String) validation.get(SEVERITY));
-        String message = (String) validation.get(MESSAGE);
+      Validation.Message message
+        = new Validation.Message(status, stringMessage);
 
-        input.setValidationMessage(severity, message);
-      } else {
-        input.setValidationMessage(MValidatedElement.Severity.OK, null);
-      }
+      messages.put((String)key, message);
     }
-  }
 
+    Status status = Status.valueOf((String) jsonObject.get(STATUS));
+
+    return new Validation(status,messages);
+  }
 }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/a46b25f5/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
new file mode 100644
index 0000000..1331c7e
--- /dev/null
+++ b/common/src/main/java/org/apache/sqoop/model/Configuration.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 Configuration {
+
+}

http://git-wip-us.apache.org/repos/asf/sqoop/blob/a46b25f5/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
new file mode 100644
index 0000000..424810c
--- /dev/null
+++ b/common/src/main/java/org/apache/sqoop/model/FormUtils.java
@@ -0,0 +1,201 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sqoop.model;
+
+import org.apache.sqoop.common.SqoopException;
+import org.apache.sqoop.validation.Status;
+import org.apache.sqoop.validation.Validation;
+
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Util class for transforming data from correctly annotated configuration
+ * objects to form structures and vice-versa.
+ */
+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.
+   *
+   * @param configuration Annotated arbitrary configuration object
+   * @return Corresponding list of forms
+   */
+  public static List<MForm> toForms(Object configuration) {
+    return toForms(configuration.getClass(), configuration);
+  }
+
+  public static List<MForm> toForms(Class klass) {
+    return toForms(klass, null);
+  }
+
+  public static List<MForm> toForms(Class klass, Object configuration) {
+    Configuration global =
+      (Configuration)klass.getAnnotation(Configuration.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());
+    }
+
+    // List of forms in order they appeared in configuration class
+    List<String> forms = new LinkedList<String>();
+
+    // Intermediate list of inputs for each defined form
+    Map<String, List<MInput<?>>> formInputs
+      = new HashMap<String, List<MInput<?>>>();
+
+    // Iterate over all declared fields
+    for (Field field : klass.getDeclaredFields()) {
+      field.setAccessible(true);
+
+      String fieldName = field.getName();
+
+      // 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
+        if(type.isPrimitive()) {
+          throw new SqoopException(ModelError.MODEL_007,
+            "Detected primitive type " + type + " for field " + fieldName);
+        }
+
+        // Instantiate corresponding MInput<?> structure
+        if(type == String.class) {
+          input = new MStringInput(fieldName, sensitive, maxLen);
+        } else if (type.isAssignableFrom(Map.class)) {
+          input = new MMapInput(fieldName);
+        } else if(type == Integer.class) {
+          input = new MIntegerInput(fieldName);
+        } 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) {
+          Object value;
+          try {
+            value = field.get(configuration);
+          } catch (IllegalAccessException e) {
+            throw new SqoopException(ModelError.MODEL_005,
+              "Issue with field " + field.getName(), e);
+          }
+          if(value == null) {
+            input.setEmpty();
+          } else {
+            input.setValue(value);
+          }
+        }
+
+        formInputs.get(form).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;
+  }
+
+  /**
+   * Move form values from form list into corresponding configuration object.
+   *
+   * @param forms Input form list
+   * @param configuration Output configuration object
+   */
+  public static void fillValues(List<MForm> forms, Object configuration) {
+    Class klass = configuration.getClass();
+
+    for(MForm form : forms) {
+      for(MInput input : form.getInputs()) {
+        Field field;
+        try {
+          field = klass.getDeclaredField(input.getName());
+        } 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);
+
+        try {
+          if(input.isEmpty()) {
+            field.set(configuration, null);
+          } else {
+            field.set(configuration, input.getValue());
+          }
+        } catch (IllegalAccessException e) {
+          throw new SqoopException(ModelError.MODEL_005,
+            "Issue with field " + field.getName(), e);
+        }
+      }
+    }
+  }
+
+  /**
+   * Apply validations on the forms.
+   *
+   * @param forms Forms that should be updated
+   * @param validation Validation that we should apply
+   */
+  public static void applyValidation(List<MForm> forms, Validation validation) {
+    Map<String, Validation.Message> messages = validation.getMessages();
+
+    for(MForm form : forms) {
+      for(MInput input : form.getInputs()) {
+        String inputName = input.getName();
+        if(messages.containsKey(inputName)){
+          Validation.Message message = messages.get(inputName);
+
+          input.setValidationMessage(message.getStatus(), message.getMessage());
+        } else {
+          input.setValidationMessage(Status.getDefault(), null);
+        }
+      }
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/sqoop/blob/a46b25f5/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
new file mode 100644
index 0000000..6b3973b
--- /dev/null
+++ b/common/src/main/java/org/apache/sqoop/model/Input.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.model;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Field annotation. Each field that user might change in configuration object
+ * need to have this annotation.
+ */
+@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.
+   *
+   * @return True if field is sensitive
+   */
+  boolean sensitive() default false;
+
+  /**
+   * Maximal length of field if applicable.
+   *
+   * @return Maximal length
+   */
+  short size() default -1;
+}

http://git-wip-us.apache.org/repos/asf/sqoop/blob/a46b25f5/common/src/main/java/org/apache/sqoop/model/MValidatedElement.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/model/MValidatedElement.java b/common/src/main/java/org/apache/sqoop/model/MValidatedElement.java
index ce8f2cd..0eafad8 100644
--- a/common/src/main/java/org/apache/sqoop/model/MValidatedElement.java
+++ b/common/src/main/java/org/apache/sqoop/model/MValidatedElement.java
@@ -17,6 +17,8 @@
  */
 package org.apache.sqoop.model;
 
+import org.apache.sqoop.validation.Status;
+
 /**
  * Element that can be validated for correctness.
  *
@@ -36,26 +38,6 @@ package org.apache.sqoop.model;
 public abstract class MValidatedElement extends MNamedElement {
 
   /**
-   * Different levels of validation severity.
-   */
-  public enum Severity {
-    /**
-     * Everything is fine, no issues with this element.
-     */
-    OK,
-
-    /**
-     * Warning is suspicious content of the element.
-     */
-    WARNING,
-
-    /**
-     * Error is incorrect, unacceptable content of the element.
-     */
-    ERROR,
-  }
-
-  /**
    * Validation message.
    *
    * One element can have only one message regardless of the type.
@@ -65,23 +47,23 @@ public abstract class MValidatedElement extends MNamedElement {
   /**
    * Severity of the message.
    */
-  private Severity validationSeverity;
+  private Status validationStatus;
 
   public MValidatedElement(String name) {
     super(name);
     // Everything is fine by default
-    this.validationSeverity = Severity.OK;
+    this.validationStatus = Status.getDefault();
   }
 
   /**
    * Set validation message and given severity.
    *
-   * @param severity Message severity
+   * @param status Message validation status
    * @param msg Message itself
    */
-  public void setValidationMessage(Severity severity, String msg) {
+  public void setValidationMessage(Status status, String msg) {
     this.validationMessage = msg;
-    this.validationSeverity = severity;
+    this.validationStatus = status;
   }
 
   /**
@@ -90,10 +72,10 @@ public abstract class MValidatedElement extends MNamedElement {
    * Return either associated message for given severity or null in case
    * that there is no message with given severity.
    *
-   * @param severity Message severity
+   * @param status Message validation status
    */
-  public String getValidationMessage(Severity severity) {
-    return (validationSeverity.equals(severity)) ? validationMessage : null;
+  public String getValidationMessage(Status status) {
+    return (validationStatus.equals(status)) ? validationMessage : null;
   }
 
   /**
@@ -106,10 +88,10 @@ public abstract class MValidatedElement extends MNamedElement {
   }
 
   /**
-   * Return message severity.
+   * Return message validation status.
    */
-  public Severity getValidationSeverity() {
-    return validationSeverity;
+  public Status getValidationStatus() {
+    return validationStatus;
   }
 
   /**
@@ -118,7 +100,7 @@ public abstract class MValidatedElement extends MNamedElement {
    * @param errMsg Error message
    */
   public void setErrorMessage(String errMsg) {
-    setValidationMessage(Severity.ERROR, errMsg);
+    setValidationMessage(Status.UNACCEPTABLE, errMsg);
   }
 
   /**
@@ -127,7 +109,7 @@ public abstract class MValidatedElement extends MNamedElement {
    * @return Error message
    */
   public String getErrorMessage() {
-    return getValidationMessage(Severity.ERROR);
+    return getValidationMessage(Status.UNACCEPTABLE);
   }
 
   /**
@@ -136,7 +118,7 @@ public abstract class MValidatedElement extends MNamedElement {
    * @param warnMsg Warning message
    */
   public void setWarningMessage(String warnMsg) {
-    setValidationMessage(Severity.WARNING, warnMsg);
+    setValidationMessage(Status.ACCEPTABLE, warnMsg);
   }
 
   /**
@@ -144,7 +126,7 @@ public abstract class MValidatedElement extends MNamedElement {
    * @return
    */
   public String getWarningMessage() {
-    return getValidationMessage(Severity.WARNING);
+    return getValidationMessage(Status.ACCEPTABLE);
   }
 
 }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/a46b25f5/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 7a9ebd8..d3467c0 100644
--- a/common/src/main/java/org/apache/sqoop/model/ModelError.java
+++ b/common/src/main/java/org/apache/sqoop/model/ModelError.java
@@ -28,6 +28,16 @@ public enum ModelError implements ErrorCode {
 
   MODEL_002("Creating MJob of different job types"),
 
+  MODEL_003("Object is not valid configuration object"),
+
+  MODEL_004("Usage of unsupported data type"),
+
+  MODEL_005("Can't get field details"),
+
+  MODEL_006("Incompatible form list and configuration object"),
+
+  MODEL_007("Primitive types in configuration objects are not allowed"),
+
   ;
 
   private final String message;

http://git-wip-us.apache.org/repos/asf/sqoop/blob/a46b25f5/common/src/main/java/org/apache/sqoop/utils/ClassLoadingUtils.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/utils/ClassLoadingUtils.java b/common/src/main/java/org/apache/sqoop/utils/ClassLoadingUtils.java
index a7a870f..0c7d09f 100644
--- a/common/src/main/java/org/apache/sqoop/utils/ClassLoadingUtils.java
+++ b/common/src/main/java/org/apache/sqoop/utils/ClassLoadingUtils.java
@@ -19,6 +19,9 @@ package org.apache.sqoop.utils;
 
 import org.apache.log4j.Logger;
 
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
 public final class ClassLoadingUtils {
 
   private static final Logger LOG = Logger.getLogger(ClassLoadingUtils.class);
@@ -46,6 +49,37 @@ public final class ClassLoadingUtils {
     return klass;
   }
 
+  public static Object instantiate(String className, Object ... args) {
+    return instantiate(loadClass(className), args);
+  }
+
+  public static Object instantiate(Class klass, Object ... args) {
+    if(klass == null) {
+      return null;
+    }
+
+    Class []argumentTypes = new Class[args.length];
+    for(int i = 0; i < args.length; i++) {
+      Class type = args[i].getClass();
+       argumentTypes[i] = type;
+    }
+
+    try {
+      Constructor constructor = klass.getConstructor(argumentTypes);
+      return constructor.newInstance(args);
+    } catch (NoSuchMethodException e) {
+      LOG.error("Can't find such constructor.", e);
+    } catch (InvocationTargetException e) {
+      LOG.error("Can't instantiate object.", e);
+    } catch (InstantiationException e) {
+      LOG.error("Can't instantiate object.", e);
+    } catch (IllegalAccessException e) {
+      LOG.error("Can't instantiate object.", e);
+    }
+
+    return null;
+  }
+
   private ClassLoadingUtils() {
     // Disable explicit object creation
   }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/a46b25f5/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 5c9fb9c..c6f25f0 100644
--- a/common/src/main/java/org/apache/sqoop/validation/Status.java
+++ b/common/src/main/java/org/apache/sqoop/validation/Status.java
@@ -66,4 +66,13 @@ public enum Status {
   public boolean canProceed() {
     return this == FINE || this == ACCEPTABLE;
   }
+
+  /**
+   * Return default validation "everything is completely fine".
+   *
+   * @return Default validation status
+   */
+  public static Status getDefault() {
+    return FINE;
+  }
 }