sqoop-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jar...@apache.org
Subject [3/3] sqoop git commit: SQOOP-1442: Sqoop2: Validations: Serialize validations over the wire for client transfer
Date Wed, 14 Oct 2015 00:00:31 GMT
SQOOP-1442: Sqoop2: Validations: Serialize validations over the wire for client transfer

(Abraham Fine via 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/d69bd34e
Tree: http://git-wip-us.apache.org/repos/asf/sqoop/tree/d69bd34e
Diff: http://git-wip-us.apache.org/repos/asf/sqoop/diff/d69bd34e

Branch: refs/heads/sqoop2
Commit: d69bd34e0b62a4fdbb6019d81bd96da53b55c9e1
Parents: 1d4d70a
Author: Jarek Jarcec Cecho <jarcec@apache.org>
Authored: Tue Oct 13 16:59:42 2015 -0700
Committer: Jarek Jarcec Cecho <jarcec@apache.org>
Committed: Tue Oct 13 16:59:42 2015 -0700

----------------------------------------------------------------------
 .../apache/sqoop/client/TestSqoopClient.java    |   5 +-
 .../org/apache/sqoop/json/ConnectorBean.java    |  40 +++---
 .../java/org/apache/sqoop/json/DriverBean.java  |  19 ++-
 .../java/org/apache/sqoop/json/JobBean.java     |  43 +++---
 .../java/org/apache/sqoop/json/LinkBean.java    |  14 +-
 .../sqoop/json/util/ConfigInputConstants.java   |   2 +
 .../json/util/ConfigInputSerialization.java     |  91 +++++++++---
 .../json/util/ConfigValidatorConstants.java     |  26 ++++
 .../org/apache/sqoop/model/ConfigUtils.java     |  60 ++++++--
 .../apache/sqoop/model/MAccountableEntity.java  |   3 +-
 .../org/apache/sqoop/model/MBooleanInput.java   |   8 +-
 .../java/org/apache/sqoop/model/MConfig.java    |   8 +-
 .../org/apache/sqoop/model/MConfigList.java     |   5 +-
 .../org/apache/sqoop/model/MDateTimeInput.java  |   8 +-
 .../org/apache/sqoop/model/MDriverConfig.java   |   6 +-
 .../java/org/apache/sqoop/model/MEnumInput.java |   7 +-
 .../org/apache/sqoop/model/MFromConfig.java     |   6 +-
 .../java/org/apache/sqoop/model/MInput.java     |   6 +-
 .../org/apache/sqoop/model/MIntegerInput.java   |   8 +-
 .../org/apache/sqoop/model/MLinkConfig.java     |   6 +-
 .../java/org/apache/sqoop/model/MListInput.java |   6 +-
 .../java/org/apache/sqoop/model/MLongInput.java |   8 +-
 .../java/org/apache/sqoop/model/MMapInput.java  |   7 +-
 .../org/apache/sqoop/model/MNamedElement.java   |   7 +-
 .../org/apache/sqoop/model/MStringInput.java    |   8 +-
 .../java/org/apache/sqoop/model/MToConfig.java  |   6 +-
 .../apache/sqoop/model/MValidatedElement.java   |  21 ++-
 .../java/org/apache/sqoop/model/MValidator.java |  68 +++++++++
 .../org/apache/sqoop/json/TestLinkBean.java     |  21 ++-
 .../org/apache/sqoop/json/TestLinksBean.java    |   3 +-
 .../apache/sqoop/json/util/BeanTestUtil.java    |   1 +
 .../apache/sqoop/json/util/ConfigTestUtil.java  |  71 ++++++----
 .../json/util/TestConfigSerialization.java      |  61 +++++++--
 .../org/apache/sqoop/model/TestConfigUtils.java |  77 +++++++----
 .../sqoop/model/TestMAccountableEntity.java     |  15 +-
 .../apache/sqoop/model/TestMBooleanInput.java   |  22 +--
 .../org/apache/sqoop/model/TestMConfig.java     |  35 ++---
 .../org/apache/sqoop/model/TestMConfigList.java |  19 +--
 .../org/apache/sqoop/model/TestMConnector.java  |  28 ++--
 .../apache/sqoop/model/TestMDateTimeInput.java  |  22 +--
 .../org/apache/sqoop/model/TestMDriver.java     |  13 +-
 .../org/apache/sqoop/model/TestMEnumInput.java  |  14 +-
 .../apache/sqoop/model/TestMIntegerInput.java   |  22 +--
 .../java/org/apache/sqoop/model/TestMJob.java   |  35 +++--
 .../org/apache/sqoop/model/TestMJobConfig.java  |  13 +-
 .../java/org/apache/sqoop/model/TestMLink.java  |  13 +-
 .../org/apache/sqoop/model/TestMLinkConfig.java |  13 +-
 .../org/apache/sqoop/model/TestMListInput.java  |  21 +--
 .../org/apache/sqoop/model/TestMMapInput.java   |  25 ++--
 .../apache/sqoop/model/TestMNamedElement.java   |   4 +-
 .../apache/sqoop/model/TestMStringInput.java    |  18 +--
 .../sqoop/model/TestMValidatedElement.java      |  11 +-
 .../org/apache/sqoop/model/TestMValidator.java  |  34 +++++
 .../jdbc/TestGenericJdbcConnectorUpgrader.java  |  12 +-
 .../kite/TestKiteConnectorUpgrader.java         |  10 +-
 .../sqoop/connector/ConnectorHandler.java       |   6 +-
 .../java/org/apache/sqoop/driver/Driver.java    |   6 +-
 .../org/apache/sqoop/repository/Repository.java |  13 +-
 .../sqoop/driver/TestDriverConfigUpgrader.java  |  47 +++++--
 .../sqoop/repository/TestJdbcRepository.java    |  17 +--
 .../common/CommonRepositoryHandler.java         |  59 ++++----
 .../sqoop/repository/derby/DerbyTestCase.java   | 137 ++++++++++---------
 .../repository/mysql/MySqlTestCase.java         |  21 +--
 .../postgresql/PostgresqlTestCase.java          |  21 +--
 .../apache/sqoop/shell/utils/ConfigFiller.java  |   3 +-
 .../sqoop/tools/tool/RepositoryLoadTool.java    |   4 +-
 66 files changed, 976 insertions(+), 493 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/sqoop/blob/d69bd34e/client/src/test/java/org/apache/sqoop/client/TestSqoopClient.java
----------------------------------------------------------------------
diff --git a/client/src/test/java/org/apache/sqoop/client/TestSqoopClient.java b/client/src/test/java/org/apache/sqoop/client/TestSqoopClient.java
index ed0badc..c962358 100644
--- a/client/src/test/java/org/apache/sqoop/client/TestSqoopClient.java
+++ b/client/src/test/java/org/apache/sqoop/client/TestSqoopClient.java
@@ -44,6 +44,7 @@ import org.apache.sqoop.model.MDriverConfig;
 import org.apache.sqoop.model.MFromConfig;
 import org.apache.sqoop.model.MLinkConfig;
 import org.apache.sqoop.model.MToConfig;
+import org.apache.sqoop.model.MValidator;
 import org.apache.sqoop.utils.MapResourceBundle;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
@@ -221,13 +222,13 @@ public class TestSqoopClient {
 
   private MConnector connector(long id) {
     MConnector connector = new MConnector("A" + id, "A" + id, "1.0" + id,
-        new MLinkConfig(null), new MFromConfig(null), new MToConfig(null));
+        new MLinkConfig(null, null), new MFromConfig(null, null), new MToConfig(null, null));
     connector.setPersistenceId(id);
     return connector;
   }
 
   private MDriver driver() {
-    MDriver driver = new MDriver(new MDriverConfig(new LinkedList<MConfig>()), "1");
+    MDriver driver = new MDriver(new MDriverConfig(new LinkedList<MConfig>(), new LinkedList<MValidator>()), "1");
     driver.setPersistenceId(1);
     return driver;
   }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/d69bd34e/common/src/main/java/org/apache/sqoop/json/ConnectorBean.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/json/ConnectorBean.java b/common/src/main/java/org/apache/sqoop/json/ConnectorBean.java
index 0322032..2509e3e 100644
--- a/common/src/main/java/org/apache/sqoop/json/ConnectorBean.java
+++ b/common/src/main/java/org/apache/sqoop/json/ConnectorBean.java
@@ -18,10 +18,12 @@
 package org.apache.sqoop.json;
 
 import static org.apache.sqoop.json.util.ConfigInputSerialization.extractConfigList;
-import static org.apache.sqoop.json.util.ConfigInputSerialization.restoreConfigList;
 import static org.apache.sqoop.json.util.ConfigBundleSerialization.extractConfigParamBundle;
 import static org.apache.sqoop.json.util.ConfigBundleSerialization.restoreConfigParamBundle;
 
+import static org.apache.sqoop.json.util.ConfigInputSerialization.restoreConfigs;
+import static org.apache.sqoop.json.util.ConfigInputSerialization.restoreValidator;
+
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -31,11 +33,13 @@ import java.util.ResourceBundle;
 import org.apache.sqoop.classification.InterfaceAudience;
 import org.apache.sqoop.classification.InterfaceStability;
 import org.apache.sqoop.common.Direction;
+import org.apache.sqoop.json.util.ConfigInputConstants;
 import org.apache.sqoop.model.MConfig;
 import org.apache.sqoop.model.MConnector;
 import org.apache.sqoop.model.MFromConfig;
 import org.apache.sqoop.model.MLinkConfig;
 import org.apache.sqoop.model.MToConfig;
+import org.apache.sqoop.model.MValidator;
 import org.json.simple.JSONArray;
 import org.json.simple.JSONObject;
 
@@ -99,22 +103,19 @@ public class ConnectorBean extends ConfigurableBean {
     connectorJsonObject.put(CONFIGURABLE_VERSION, connector.getVersion());
     connectorJsonObject.put(
         CONNECTOR_LINK_CONFIG,
-        extractConfigList(connector.getLinkConfig().getConfigs(), connector.getLinkConfig()
-            .getType(), skipSensitive));
+        extractConfigList(connector.getLinkConfig(), skipSensitive));
 
     connectorJsonObject.put(CONNECTOR_JOB_CONFIG, new JSONObject());
     // add sub fields to the job config for from and to
     if (connector.getFromConfig() != null) {
       ((JSONObject) connectorJsonObject.get(CONNECTOR_JOB_CONFIG)).put(
           Direction.FROM,
-          extractConfigList(connector.getFromConfig().getConfigs(), connector.getFromConfig()
-              .getType(), skipSensitive));
+          extractConfigList(connector.getFromConfig(), skipSensitive));
     }
     if (connector.getToConfig() != null) {
       ((JSONObject) connectorJsonObject.get(CONNECTOR_JOB_CONFIG)).put(
           Direction.TO,
-          extractConfigList(connector.getToConfig().getConfigs(), connector.getToConfig()
-              .getType(), skipSensitive));
+          extractConfigList(connector.getToConfig(), skipSensitive));
     }
     // add the config-param inside each connector
     connectorJsonObject.put(ALL_CONFIGS, new JSONObject());
@@ -148,28 +149,33 @@ public class ConnectorBean extends ConfigurableBean {
     String className = (String) object.get(CLASS);
     String version = (String) object.get(CONFIGURABLE_VERSION);
 
-    List<MConfig> linkConfigs = restoreConfigList((JSONArray) object
-        .get(CONNECTOR_LINK_CONFIG));
+    JSONObject jsonLink = (JSONObject) object.get(CONNECTOR_LINK_CONFIG);
+    List<MConfig> linkConfigs = restoreConfigs((JSONArray) jsonLink.get(ConfigInputConstants.CONFIGS));
+    List<MValidator> linkValidators = restoreValidator((JSONArray) jsonLink
+      .get(ConfigInputConstants.CONFIG_VALIDATORS));
 
     // parent that encapsulates both the from/to configs
     JSONObject jobConfigJson = (JSONObject) object.get(CONNECTOR_JOB_CONFIG);
-    JSONArray fromJobConfigJson = (JSONArray) jobConfigJson.get(Direction.FROM.name());
-    JSONArray toJobConfigJson = (JSONArray) jobConfigJson.get(Direction.TO.name());
+    JSONObject fromJobConfigJson = (JSONObject) jobConfigJson.get(Direction.FROM.name());
+    JSONObject toJobConfigJson = (JSONObject) jobConfigJson.get(Direction.TO.name());
 
     MFromConfig fromConfig = null;
     MToConfig toConfig = null;
     if (fromJobConfigJson != null) {
-
-      List<MConfig> fromJobConfig = restoreConfigList(fromJobConfigJson);
-      fromConfig = new MFromConfig(fromJobConfig);
+      List<MConfig> fromLinkConfigs = restoreConfigs((JSONArray) fromJobConfigJson.get(ConfigInputConstants.CONFIGS));
+      List<MValidator> fromLinkValidators = restoreValidator((JSONArray)
+        fromJobConfigJson.get(ConfigInputConstants.CONFIG_VALIDATORS));
+      fromConfig = new MFromConfig(fromLinkConfigs, fromLinkValidators);
 
     }
     if (toJobConfigJson != null) {
-      List<MConfig> toJobConfig = restoreConfigList(toJobConfigJson);
-      toConfig = new MToConfig(toJobConfig);
+      List<MConfig> toLinkConfigs = restoreConfigs((JSONArray) toJobConfigJson.get(ConfigInputConstants.CONFIGS));
+      List<MValidator> toLinkValidators = restoreValidator((JSONArray)
+        toJobConfigJson.get(ConfigInputConstants.CONFIG_VALIDATORS));
+      toConfig = new MToConfig(toLinkConfigs, toLinkValidators);
     }
 
-    MLinkConfig linkConfig = new MLinkConfig(linkConfigs);
+    MLinkConfig linkConfig = new MLinkConfig(linkConfigs, linkValidators);
     MConnector connector = new MConnector(uniqueName, className, version, linkConfig, fromConfig,
         toConfig);
 

http://git-wip-us.apache.org/repos/asf/sqoop/blob/d69bd34e/common/src/main/java/org/apache/sqoop/json/DriverBean.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/json/DriverBean.java b/common/src/main/java/org/apache/sqoop/json/DriverBean.java
index 6012917..6f03be2 100644
--- a/common/src/main/java/org/apache/sqoop/json/DriverBean.java
+++ b/common/src/main/java/org/apache/sqoop/json/DriverBean.java
@@ -18,18 +18,24 @@
 package org.apache.sqoop.json;
 
 import static org.apache.sqoop.json.util.ConfigInputSerialization.extractConfigList;
-import static org.apache.sqoop.json.util.ConfigInputSerialization.restoreConfigList;
 import static org.apache.sqoop.json.util.ConfigBundleSerialization.extractConfigParamBundle;
 import static org.apache.sqoop.json.util.ConfigBundleSerialization.restoreConfigParamBundle;
 
+
+
+import static org.apache.sqoop.json.util.ConfigInputSerialization.restoreConfigs;
+import static org.apache.sqoop.json.util.ConfigInputSerialization.restoreValidator;
+
 import java.util.List;
 import java.util.ResourceBundle;
 
 import org.apache.sqoop.classification.InterfaceAudience;
 import org.apache.sqoop.classification.InterfaceStability;
+import org.apache.sqoop.json.util.ConfigInputConstants;
 import org.apache.sqoop.model.MConfig;
 import org.apache.sqoop.model.MDriver;
 import org.apache.sqoop.model.MDriverConfig;
+import org.apache.sqoop.model.MValidator;
 import org.json.simple.JSONArray;
 import org.json.simple.JSONObject;
 /**
@@ -66,8 +72,8 @@ public class DriverBean extends ConfigurableBean {
   @SuppressWarnings("unchecked")
   @Override
   public JSONObject extract(boolean skipSensitive) {
-    JSONArray configs =
-      extractConfigList(driver.getDriverConfig().getConfigs(), driver.getDriverConfig().getType(), skipSensitive);
+    JSONObject configs =
+      extractConfigList(driver.getDriverConfig(), skipSensitive);
 
     JSONObject result = new JSONObject();
     result.put(ID, driver.getPersistenceId());
@@ -81,8 +87,11 @@ public class DriverBean extends ConfigurableBean {
   public void restore(JSONObject jsonObject) {
     long id = (Long) jsonObject.get(ID);
     String driverVersion = (String) jsonObject.get(CONFIGURABLE_VERSION);
-    List<MConfig> driverConfig = restoreConfigList((JSONArray) jsonObject.get(DRIVER_JOB_CONFIG));
-    driver = new MDriver(new MDriverConfig(driverConfig), driverVersion);
+    JSONObject driverJobConfig = (JSONObject) jsonObject.get(DRIVER_JOB_CONFIG);
+    List<MConfig> driverConfigs = restoreConfigs((JSONArray) driverJobConfig.get(ConfigInputConstants.CONFIGS));
+    List<MValidator> driverValidators = restoreValidator((JSONArray)
+      driverJobConfig.get(ConfigInputConstants.CONFIG_VALIDATORS));
+    driver = new MDriver(new MDriverConfig(driverConfigs, driverValidators), driverVersion);
     driver.setPersistenceId(id);
     driverConfigBundle = restoreConfigParamBundle((JSONObject) jsonObject.get(ALL_CONFIGS));
   }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/d69bd34e/common/src/main/java/org/apache/sqoop/json/JobBean.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/json/JobBean.java b/common/src/main/java/org/apache/sqoop/json/JobBean.java
index e983075..df7a804 100644
--- a/common/src/main/java/org/apache/sqoop/json/JobBean.java
+++ b/common/src/main/java/org/apache/sqoop/json/JobBean.java
@@ -18,7 +18,8 @@
 package org.apache.sqoop.json;
 
 import static org.apache.sqoop.json.util.ConfigInputSerialization.extractConfigList;
-import static org.apache.sqoop.json.util.ConfigInputSerialization.restoreConfigList;
+import static org.apache.sqoop.json.util.ConfigInputSerialization.restoreConfigs;
+import static org.apache.sqoop.json.util.ConfigInputSerialization.restoreValidator;
 
 import java.util.ArrayList;
 import java.util.Date;
@@ -29,12 +30,14 @@ import java.util.ResourceBundle;
 
 import org.apache.sqoop.classification.InterfaceAudience;
 import org.apache.sqoop.classification.InterfaceStability;
-import org.apache.sqoop.common.Direction;
+import org.apache.sqoop.json.util.ConfigInputConstants;
+import org.apache.sqoop.json.util.ConfigValidatorConstants;
 import org.apache.sqoop.model.MConfig;
 import org.apache.sqoop.model.MDriverConfig;
 import org.apache.sqoop.model.MFromConfig;
 import org.apache.sqoop.model.MJob;
 import org.apache.sqoop.model.MToConfig;
+import org.apache.sqoop.model.MValidator;
 import org.json.simple.JSONArray;
 import org.json.simple.JSONObject;
 
@@ -138,16 +141,13 @@ public class JobBean implements JsonBean {
     object.put(TO_LINK_ID, job.getToLinkId());
     // job configs
     MFromConfig fromConfigList = job.getFromJobConfig();
-    object.put(FROM_CONFIG_VALUES,
-        extractConfigList(fromConfigList.getConfigs(), fromConfigList.getType(), skipSensitive));
+    object.put(FROM_CONFIG_VALUES, extractConfigList(fromConfigList, skipSensitive));
     MToConfig toConfigList = job.getToJobConfig();
-    object.put(TO_CONFIG_VALUES,
-        extractConfigList(toConfigList.getConfigs(), toConfigList.getType(), skipSensitive));
+    object.put(TO_CONFIG_VALUES, extractConfigList(toConfigList, skipSensitive));
     MDriverConfig driverConfigList = job.getDriverConfig();
     object.put(
         DRIVER_CONFIG_VALUES,
-        extractConfigList(driverConfigList.getConfigs(), driverConfigList.getType(),
-            skipSensitive));
+        extractConfigList(driverConfigList, skipSensitive));
 
     return object;
   }
@@ -172,22 +172,31 @@ public class JobBean implements JsonBean {
     long toConnectorId = (Long) object.get(TO_CONNECTOR_ID);
     long fromConnectionId = (Long) object.get(FROM_LINK_ID);
     long toConnectionId = (Long) object.get(TO_LINK_ID);
-    JSONArray fromConfigJson = (JSONArray) object.get(FROM_CONFIG_VALUES);
-    JSONArray toConfigJson = (JSONArray) object.get(TO_CONFIG_VALUES);
-    JSONArray driverConfigJson = (JSONArray) object.get(DRIVER_CONFIG_VALUES);
+    JSONObject fromConfigJson = (JSONObject) object.get(FROM_CONFIG_VALUES);
+    JSONObject toConfigJson = (JSONObject) object.get(TO_CONFIG_VALUES);
+    JSONObject driverConfigJson = (JSONObject) object.get(DRIVER_CONFIG_VALUES);
 
-    List<MConfig> fromConfig = restoreConfigList(fromConfigJson);
-    List<MConfig> toConfig = restoreConfigList(toConfigJson);
-    List<MConfig> driverConfig = restoreConfigList(driverConfigJson);
+    List<MConfig> fromConfigs = restoreConfigs((JSONArray) fromConfigJson.get(ConfigInputConstants.CONFIGS));
+    List<MValidator> fromValidators = restoreValidator((JSONArray)
+      fromConfigJson.get(ConfigInputConstants.CONFIG_VALIDATORS));
+
+    List<MConfig> toConfigs = restoreConfigs((JSONArray) toConfigJson.get(ConfigInputConstants.CONFIGS));
+    List<MValidator> toValidators = restoreValidator((JSONArray)
+      toConfigJson.get(ConfigInputConstants.CONFIG_VALIDATORS));
+
+    List<MConfig> driverConfigs = restoreConfigs((JSONArray) driverConfigJson
+      .get(ConfigInputConstants.CONFIGS));
+    List<MValidator> driverValidators = restoreValidator((JSONArray)
+      driverConfigJson.get(ConfigInputConstants.CONFIG_VALIDATORS));
 
     MJob job = new MJob(
       fromConnectorId,
       toConnectorId,
       fromConnectionId,
       toConnectionId,
-      new MFromConfig(fromConfig),
-      new MToConfig(toConfig),
-      new MDriverConfig(driverConfig)
+      new MFromConfig(fromConfigs, fromValidators),
+      new MToConfig(toConfigs, toValidators),
+      new MDriverConfig(driverConfigs, driverValidators)
     );
 
     job.setPersistenceId((Long) object.get(ID));

http://git-wip-us.apache.org/repos/asf/sqoop/blob/d69bd34e/common/src/main/java/org/apache/sqoop/json/LinkBean.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/json/LinkBean.java b/common/src/main/java/org/apache/sqoop/json/LinkBean.java
index 2e2406f..99e7319 100644
--- a/common/src/main/java/org/apache/sqoop/json/LinkBean.java
+++ b/common/src/main/java/org/apache/sqoop/json/LinkBean.java
@@ -18,7 +18,8 @@
 package org.apache.sqoop.json;
 
 import static org.apache.sqoop.json.util.ConfigInputSerialization.extractConfigList;
-import static org.apache.sqoop.json.util.ConfigInputSerialization.restoreConfigList;
+import static org.apache.sqoop.json.util.ConfigInputSerialization.restoreConfigs;
+import static org.apache.sqoop.json.util.ConfigInputSerialization.restoreValidator;
 
 import java.util.ArrayList;
 import java.util.Date;
@@ -29,9 +30,11 @@ import java.util.ResourceBundle;
 
 import org.apache.sqoop.classification.InterfaceAudience;
 import org.apache.sqoop.classification.InterfaceStability;
+import org.apache.sqoop.json.util.ConfigInputConstants;
 import org.apache.sqoop.model.MConfig;
 import org.apache.sqoop.model.MLink;
 import org.apache.sqoop.model.MLinkConfig;
+import org.apache.sqoop.model.MValidator;
 import org.json.simple.JSONArray;
 import org.json.simple.JSONObject;
 
@@ -118,7 +121,7 @@ public class LinkBean implements JsonBean {
     linkJsonObject.put(UPDATE_DATE, link.getLastUpdateDate().getTime());
     linkJsonObject.put(CONNECTOR_ID, link.getConnectorId());
     linkJsonObject.put(LINK_CONFIG_VALUES,
-      extractConfigList(link.getConnectorLinkConfig().getConfigs(), link.getConnectorLinkConfig().getType(), skipSensitive));
+      extractConfigList(link.getConnectorLinkConfig(), skipSensitive));
     return linkJsonObject;
   }
 
@@ -139,9 +142,10 @@ public class LinkBean implements JsonBean {
   private MLink restoreLink(Object obj) {
     JSONObject object = (JSONObject) obj;
     long connectorId = (Long) object.get(CONNECTOR_ID);
-    JSONArray connectorLinkConfig = (JSONArray) object.get(LINK_CONFIG_VALUES);
-    List<MConfig> linkConfig = restoreConfigList(connectorLinkConfig);
-    MLink link = new MLink(connectorId, new MLinkConfig(linkConfig));
+    JSONObject connectorLinkConfig = (JSONObject) object.get(LINK_CONFIG_VALUES);
+    List<MConfig> linkConfigs = restoreConfigs((JSONArray) connectorLinkConfig.get(ConfigInputConstants.CONFIGS));
+    List<MValidator> linkValidators = restoreValidator((JSONArray) connectorLinkConfig.get(ConfigInputConstants.CONFIG_VALIDATORS));
+    MLink link = new MLink(connectorId, new MLinkConfig(linkConfigs, linkValidators));
     link.setPersistenceId((Long) object.get(ID));
     link.setName((String) object.get(NAME));
     link.setEnabled((Boolean) object.get(ENABLED));

http://git-wip-us.apache.org/repos/asf/sqoop/blob/d69bd34e/common/src/main/java/org/apache/sqoop/json/util/ConfigInputConstants.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/json/util/ConfigInputConstants.java b/common/src/main/java/org/apache/sqoop/json/util/ConfigInputConstants.java
index b301563..6eab685 100644
--- a/common/src/main/java/org/apache/sqoop/json/util/ConfigInputConstants.java
+++ b/common/src/main/java/org/apache/sqoop/json/util/ConfigInputConstants.java
@@ -32,6 +32,7 @@ public class ConfigInputConstants {
   public static final String CONFIG_NAME = "name";
   public static final String CONFIG_TYPE = "type";
   public static final String CONFIG_INPUTS = "inputs";
+  public static final String CONFIGS = "configs";
   public static final String CONFIG_INPUT_NAME = "name";
   public static final String CONFIG_INPUT_TYPE = "type";
   public static final String CONFIG_INPUT_SENSITIVE = "sensitive";
@@ -41,6 +42,7 @@ public class ConfigInputConstants {
   public static final String CONFIG_INPUT_OVERRIDES = "overrides";
   public static final String CONFIG_INPUT_VALUE = "value";
   public static final String CONFIG_INPUT_ENUM_VALUES = "values";
+  public static final String CONFIG_VALIDATORS = "validators";
 
   private ConfigInputConstants() {
 

http://git-wip-us.apache.org/repos/asf/sqoop/blob/d69bd34e/common/src/main/java/org/apache/sqoop/json/util/ConfigInputSerialization.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/json/util/ConfigInputSerialization.java b/common/src/main/java/org/apache/sqoop/json/util/ConfigInputSerialization.java
index 03e869c..bd4f5c4 100644
--- a/common/src/main/java/org/apache/sqoop/json/util/ConfigInputSerialization.java
+++ b/common/src/main/java/org/apache/sqoop/json/util/ConfigInputSerialization.java
@@ -23,6 +23,7 @@ import org.apache.sqoop.classification.InterfaceStability;
 import org.apache.sqoop.common.SqoopException;
 import org.apache.sqoop.model.InputEditable;
 import org.apache.sqoop.model.MBooleanInput;
+import org.apache.sqoop.model.MConfigList;
 import org.apache.sqoop.model.MDateTimeInput;
 import org.apache.sqoop.model.MEnumInput;
 import org.apache.sqoop.model.MConfig;
@@ -34,6 +35,7 @@ import org.apache.sqoop.model.MListInput;
 import org.apache.sqoop.model.MLongInput;
 import org.apache.sqoop.model.MMapInput;
 import org.apache.sqoop.model.MStringInput;
+import org.apache.sqoop.model.MValidator;
 import org.json.simple.JSONArray;
 import org.json.simple.JSONObject;
 
@@ -51,18 +53,23 @@ public final class ConfigInputSerialization {
   /**
    * Transform given list of configs to JSON Array object.
    *
-   * @param mConfigs List of configs.
+   * @param mConfigList List of configs.
    * @return JSON object with serialized config of the list.
    */
   @SuppressWarnings("unchecked")
-  public static JSONArray extractConfigList(List<MConfig> mConfigs, MConfigType type,
-      boolean skipSensitive) {
+  public static JSONObject extractConfigList(MConfigList mConfigList, boolean skipSensitive) {
+    JSONObject jsonConfigList = new JSONObject();
+
+    jsonConfigList.put(ConfigInputConstants.CONFIG_VALIDATORS, extractValidators(mConfigList.getValidators()));
+
     JSONArray configs = new JSONArray();
 
-    for (MConfig mConfig : mConfigs) {
-      configs.add(extractConfig(mConfig, type, skipSensitive));
+    for (MConfig mConfig : mConfigList.getConfigs()) {
+      configs.add(extractConfig(mConfig, mConfigList.getType(), skipSensitive));
     }
-    return configs;
+
+    jsonConfigList.put(ConfigInputConstants.CONFIGS, configs);
+    return jsonConfigList;
   }
 
   /**
@@ -78,6 +85,9 @@ public final class ConfigInputSerialization {
     config.put(ConfigInputConstants.CONFIG_ID, mConfig.getPersistenceId());
     config.put(ConfigInputConstants.CONFIG_NAME, mConfig.getName());
     config.put(ConfigInputConstants.CONFIG_TYPE, type.name());
+
+    config.put(ConfigInputConstants.CONFIG_VALIDATORS, extractValidators(mConfig.getValidators()));
+
     JSONArray mInputs = new JSONArray();
     config.put(ConfigInputConstants.CONFIG_INPUTS, mInputs);
 
@@ -90,6 +100,8 @@ public final class ConfigInputSerialization {
       input.put(ConfigInputConstants.CONFIG_INPUT_EDITABLE, mInput.getEditable().name());
       input.put(ConfigInputConstants.CONFIG_INPUT_OVERRIDES, mInput.getOverrides());
 
+      input.put(ConfigInputConstants.CONFIG_VALIDATORS, extractValidators(mInput.getValidators()));
+
       // String specific serialization
       if (mInput.getType() == MInputType.STRING) {
         input.put(ConfigInputConstants.CONFIG_INPUT_SIZE,
@@ -125,12 +137,46 @@ public final class ConfigInputSerialization {
   }
 
   /**
+   * Extract list of MValidators to JSONArray.
+   *
+   * @param mValidators List of MValidators
+   * @return JSONArray containing json objects representing the MValidators
+   */
+  public static JSONArray extractValidators(List<MValidator> mValidators) {
+    JSONArray jsonValidators = new JSONArray();
+    for (MValidator mValidator : mValidators) {
+      JSONObject jsonValidator = new JSONObject();
+      jsonValidator.put(ConfigValidatorConstants.VALIDATOR_CLASS, mValidator.getValidatorClass());
+      jsonValidator.put(ConfigValidatorConstants.VALIDATOR_STR_ARG, mValidator.getStrArg());
+      jsonValidators.add(jsonValidator);
+    }
+    return jsonValidators;
+  }
+
+  /**
+   * Restore List of MValidations from JSON Array.
+   *
+   * @param jsonValidators JSON array representing list of MValidators
+   * @return Restored list of MValidations
+   */
+  public static List<MValidator> restoreValidator(JSONArray jsonValidators) {
+    List<MValidator> mValidators = new ArrayList<>();
+    for (int validatorCounter = 0; validatorCounter < jsonValidators.size(); validatorCounter++) {
+      JSONObject jsonValidator = (JSONObject) jsonValidators.get(validatorCounter);
+      String validatorClassName = (String) jsonValidator.get(ConfigValidatorConstants.VALIDATOR_CLASS);
+      String validatorStrArg = (String) jsonValidator.get(ConfigValidatorConstants.VALIDATOR_STR_ARG);
+      mValidators.add(new MValidator(validatorClassName, validatorStrArg));
+    }
+    return mValidators;
+  }
+
+  /**
    * Restore List of MConfigs from JSON Array.
    *
    * @param configs JSON array representing list of MConfigs
    * @return Restored list of MConfigs
    */
-  public static List<MConfig> restoreConfigList(JSONArray configs) {
+  public static List<MConfig> restoreConfigs(JSONArray configs) {
     List<MConfig> mConfigs = new ArrayList<MConfig>();
 
     for (int i = 0; i < configs.size(); i++) {
@@ -163,40 +209,43 @@ public final class ConfigInputSerialization {
       String overrides = (String) input.get(ConfigInputConstants.CONFIG_INPUT_OVERRIDES);
       String sensitveKeyPattern = (String) input.get(ConfigInputConstants.CONFIG_INPUT_SENSITIVE_KEY_PATTERN);
 
+      List<MValidator> mValidatorsForInput = restoreValidator((JSONArray)
+        input.get(ConfigInputConstants.CONFIG_VALIDATORS));
+
       MInput mInput = null;
       switch (type) {
       case STRING: {
         long size = (Long) input.get(ConfigInputConstants.CONFIG_INPUT_SIZE);
-        mInput = new MStringInput(name, sensitive.booleanValue(), editable, overrides, (short) size);
+        mInput = new MStringInput(name, sensitive.booleanValue(), editable, overrides, (short) size, mValidatorsForInput);
         break;
       }
       case MAP: {
-        mInput = new MMapInput(name, sensitive.booleanValue(), editable, overrides, sensitveKeyPattern);
+        mInput = new MMapInput(name, sensitive.booleanValue(), editable, overrides, sensitveKeyPattern, mValidatorsForInput);
         break;
       }
       case INTEGER: {
-        mInput = new MIntegerInput(name, sensitive.booleanValue(), editable, overrides);
+        mInput = new MIntegerInput(name, sensitive.booleanValue(), editable, overrides, mValidatorsForInput);
         break;
       }
       case LONG: {
-        mInput = new MLongInput(name, sensitive.booleanValue(), editable, overrides);
+        mInput = new MLongInput(name, sensitive.booleanValue(), editable, overrides, mValidatorsForInput);
         break;
       }
       case BOOLEAN: {
-        mInput = new MBooleanInput(name, sensitive.booleanValue(), editable, overrides);
+        mInput = new MBooleanInput(name, sensitive.booleanValue(), editable, overrides, mValidatorsForInput);
         break;
       }
       case ENUM: {
         String values = (String) input.get(ConfigInputConstants.CONFIG_INPUT_ENUM_VALUES);
-        mInput = new MEnumInput(name, sensitive.booleanValue(), editable, overrides, values.split(","));
+        mInput = new MEnumInput(name, sensitive.booleanValue(), editable, overrides, values.split(","), mValidatorsForInput);
         break;
       }
       case LIST: {
-        mInput = new MListInput(name, sensitive.booleanValue(), editable, overrides);
+        mInput = new MListInput(name, sensitive.booleanValue(), editable, overrides, mValidatorsForInput);
         break;
       }
       case DATETIME: {
-        mInput = new MDateTimeInput(name, sensitive.booleanValue(), editable, overrides);
+        mInput = new MDateTimeInput(name, sensitive.booleanValue(), editable, overrides, mValidatorsForInput);
         break;
       }
       default:
@@ -230,12 +279,16 @@ public final class ConfigInputSerialization {
       mInputs.add(mInput);
     }
 
-    MConfig mConfig = new MConfig((String) config.get(ConfigInputConstants.CONFIG_NAME), mInputs);
+
+
+    List<MValidator> mValidatorsForConfig = restoreValidator((JSONArray)
+      config.get(ConfigInputConstants.CONFIG_VALIDATORS));
+    MConfig mConfig = new MConfig((String) config.get(ConfigInputConstants.CONFIG_NAME), mInputs, mValidatorsForConfig);
     mConfig.setPersistenceId((Long) config.get(ConfigInputConstants.CONFIG_ID));
-    return mConfig;
-  }
+      return mConfig;
+    }
 
-  private ConfigInputSerialization() {
+    private ConfigInputSerialization() {
     // Do not instantiate
   }
 }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/d69bd34e/common/src/main/java/org/apache/sqoop/json/util/ConfigValidatorConstants.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/json/util/ConfigValidatorConstants.java b/common/src/main/java/org/apache/sqoop/json/util/ConfigValidatorConstants.java
new file mode 100644
index 0000000..8e65b55
--- /dev/null
+++ b/common/src/main/java/org/apache/sqoop/json/util/ConfigValidatorConstants.java
@@ -0,0 +1,26 @@
+/**
+ * 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.json.util;
+
+/**
+ * Constants related to validators
+ */
+public class ConfigValidatorConstants {
+  public static final String VALIDATOR_CLASS = "validator-class";
+  public static final String VALIDATOR_STR_ARG = "validator-str-arg";
+}

http://git-wip-us.apache.org/repos/asf/sqoop/blob/d69bd34e/common/src/main/java/org/apache/sqoop/model/ConfigUtils.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/model/ConfigUtils.java b/common/src/main/java/org/apache/sqoop/model/ConfigUtils.java
index 493de8d..aa416e7 100644
--- a/common/src/main/java/org/apache/sqoop/model/ConfigUtils.java
+++ b/common/src/main/java/org/apache/sqoop/model/ConfigUtils.java
@@ -21,7 +21,6 @@ import org.apache.commons.lang.StringUtils;
 import org.apache.sqoop.classification.InterfaceAudience;
 import org.apache.sqoop.classification.InterfaceStability;
 import org.apache.sqoop.common.SqoopException;
-import org.apache.sqoop.error.code.CommonRepositoryError;
 import org.apache.sqoop.json.JSONUtils;
 import org.apache.sqoop.utils.ClassUtils;
 import org.apache.sqoop.validation.ConfigValidationRunner;
@@ -125,6 +124,11 @@ public class  ConfigUtils {
         "Missing annotation ConfigClass on class " + klass.getName());
     }
 
+    List<MValidator> mValidatorsForConfigClass = new ArrayList<>();
+    for (Validator validator : global.validators()) {
+      mValidatorsForConfigClass.add(getMValidator(validator));
+    }
+
     // Intermediate list of inputs
     List<MInput<?>> inputs = new LinkedList<MInput<?>>();
 
@@ -140,6 +144,10 @@ public class  ConfigUtils {
       Input inputAnnotation = field.getAnnotation(Input.class);
 
       if(inputAnnotation != null) {
+        List<MValidator> mValidatorsForInput = new ArrayList<>();
+        for (Validator validator : inputAnnotation.validators()) {
+          mValidatorsForInput.add(getMValidator(validator));
+        }
         boolean sensitive = inputAnnotation.sensitive();
         short maxLen = inputAnnotation.size();
         InputEditable editable = inputAnnotation.editable();
@@ -157,22 +165,22 @@ public class  ConfigUtils {
 
         // Instantiate corresponding MInput<?> structure
         if (type == String.class) {
-          input = new MStringInput(inputName, sensitive, editable, overrides, maxLen);
+          input = new MStringInput(inputName, sensitive, editable, overrides, maxLen, mValidatorsForInput);
         } else if (type.isAssignableFrom(Map.class)) {
-          input = new MMapInput(inputName, sensitive, editable, overrides, sensitiveKeyPattern);
+          input = new MMapInput(inputName, sensitive, editable, overrides, sensitiveKeyPattern, mValidatorsForInput);
         } else if (type == Integer.class) {
-          input = new MIntegerInput(inputName, sensitive, editable, overrides);
+          input = new MIntegerInput(inputName, sensitive, editable, overrides, mValidatorsForInput);
         } else if (type == Long.class) {
-          input = new MLongInput(inputName, sensitive, editable, overrides);
+          input = new MLongInput(inputName, sensitive, editable, overrides, mValidatorsForInput);
         } else if (type == Boolean.class) {
-          input = new MBooleanInput(inputName, sensitive, editable, overrides);
+          input = new MBooleanInput(inputName, sensitive, editable, overrides, mValidatorsForInput);
         } else if (type.isEnum()) {
           input = new MEnumInput(inputName, sensitive, editable, overrides,
-              ClassUtils.getEnumStrings(type));
+              ClassUtils.getEnumStrings(type), mValidatorsForInput);
         } else if (type.isAssignableFrom(List.class)) {
-          input = new MListInput(inputName, sensitive, editable, overrides);
+          input = new MListInput(inputName, sensitive, editable, overrides, mValidatorsForInput);
         } else if (type == DateTime.class) {
-          input = new MDateTimeInput(inputName, sensitive, editable, overrides);
+          input = new MDateTimeInput(inputName, sensitive, editable, overrides, mValidatorsForInput);
         } else {
           throw new SqoopException(ModelError.MODEL_004, "Unsupported type "
               + type.getName() + " for input " + fieldName);
@@ -203,7 +211,7 @@ public class  ConfigUtils {
         inputs.add(input);
       }
     }
-    MConfig config = new MConfig(configName, inputs);
+    MConfig config = new MConfig(configName, inputs, mValidatorsForConfigClass);
     // validation has to happen only when all inputs have been parsed
     for (MInput<?> input : config.getInputs()) {
       validateInputOverridesAttribute(input, config);
@@ -615,20 +623,38 @@ public class  ConfigUtils {
   }
 
   public static ConfigurationClass getConfigurationClassAnnotation(Object object, boolean strict) {
-    ConfigurationClass annotation = object.getClass().getAnnotation(ConfigurationClass.class);
+    return getConfigurationClassAnnotation(object.getClass(), strict);
+  }
+
+  public static ConfigurationClass getConfigurationClassAnnotation(Class<?> klass, boolean strict) {
+    ConfigurationClass annotation = klass.getAnnotation(ConfigurationClass.class);
 
     if(strict && annotation == null) {
-      throw new SqoopException(ModelError.MODEL_003, "Missing annotation ConfigurationGroupClass on class " + object.getClass().getName());
+      throw new SqoopException(ModelError.MODEL_003, "Missing annotation ConfigurationGroupClass on class " + klass.getName());
     }
 
     return annotation;
   }
 
+  public static List<MValidator> getMValidatorsFromConfigurationClass(Class<?> klass) {
+    ConfigurationClass annotation = getConfigurationClassAnnotation(klass, true);
+
+    List<MValidator> mValidators = new ArrayList<>();
+    for (Validator validator : annotation.validators()) {
+      mValidators.add(getMValidator(validator));
+    }
+    return mValidators;
+  }
+
   public static ConfigClass getConfigClassAnnotation(Object object, boolean strict) {
-    ConfigClass annotation = object.getClass().getAnnotation(ConfigClass.class);
+    return getConfigClassAnnotation(object.getClass(), strict);
+  }
+
+  public static ConfigClass getConfigClassAnnotation(Class<?> klass, boolean strict) {
+    ConfigClass annotation = klass.getAnnotation(ConfigClass.class);
 
     if(strict && annotation == null) {
-      throw new SqoopException(ModelError.MODEL_003, "Missing annotation ConfigurationGroupClass on class " + object.getClass().getName());
+      throw new SqoopException(ModelError.MODEL_003, "Missing annotation ConfigurationGroupClass on class " + klass.getName());
     }
 
     return annotation;
@@ -644,6 +670,8 @@ public class  ConfigUtils {
     return annotation;
   }
 
+
+
   public static Input getInputAnnotation(Field field, boolean strict) {
     Input annotation = field.getAnnotation(Input.class);
 
@@ -711,4 +739,8 @@ public class  ConfigUtils {
       }
     });
   }
+
+  public static MValidator getMValidator(Validator validator) {
+    return new MValidator(validator.value().getName(), validator.strArg());
+  }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/sqoop/blob/d69bd34e/common/src/main/java/org/apache/sqoop/model/MAccountableEntity.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/model/MAccountableEntity.java b/common/src/main/java/org/apache/sqoop/model/MAccountableEntity.java
index 1b350f7..2bd0ead 100644
--- a/common/src/main/java/org/apache/sqoop/model/MAccountableEntity.java
+++ b/common/src/main/java/org/apache/sqoop/model/MAccountableEntity.java
@@ -20,6 +20,7 @@ package org.apache.sqoop.model;
 import org.apache.sqoop.classification.InterfaceAudience;
 import org.apache.sqoop.classification.InterfaceStability;
 
+import java.util.Collections;
 import java.util.Date;
 
 /**
@@ -64,7 +65,7 @@ abstract public class MAccountableEntity extends MNamedElement {
    * the accountable entity is enabled.
    */
   public MAccountableEntity() {
-    super((String)null);
+    super((String)null, Collections.EMPTY_LIST);
     this.creationUser = null;
     this.creationDate = new Date();
     this.lastUpdateUser = this.creationUser;

http://git-wip-us.apache.org/repos/asf/sqoop/blob/d69bd34e/common/src/main/java/org/apache/sqoop/model/MBooleanInput.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/model/MBooleanInput.java b/common/src/main/java/org/apache/sqoop/model/MBooleanInput.java
index d55a0e7..f734375 100644
--- a/common/src/main/java/org/apache/sqoop/model/MBooleanInput.java
+++ b/common/src/main/java/org/apache/sqoop/model/MBooleanInput.java
@@ -20,6 +20,8 @@ package org.apache.sqoop.model;
 import org.apache.sqoop.classification.InterfaceAudience;
 import org.apache.sqoop.classification.InterfaceStability;
 
+import java.util.List;
+
 /**
  * Represents a <tt>Boolean</tt> input.
  */
@@ -27,8 +29,8 @@ import org.apache.sqoop.classification.InterfaceStability;
 @InterfaceStability.Unstable
 public class MBooleanInput extends MInput<Boolean> {
 
-  public MBooleanInput(String name, boolean sensitive, InputEditable editable, String overrides) {
-    super(name, sensitive, editable, overrides);
+  public MBooleanInput(String name, boolean sensitive, InputEditable editable, String overrides, List<MValidator> mValidators) {
+    super(name, sensitive, editable, overrides, mValidators);
   }
 
   @Override
@@ -78,7 +80,7 @@ public class MBooleanInput extends MInput<Boolean> {
 
   @Override
   public Object clone(boolean cloneWithValue) {
-    MBooleanInput copy = new MBooleanInput(getName(), isSensitive(), getEditable(), getOverrides());
+    MBooleanInput copy = new MBooleanInput(getName(), isSensitive(), getEditable(), getOverrides(), getCloneOfValidators());
     copy.setPersistenceId(getPersistenceId());
     if(cloneWithValue) {
       copy.setValue(getValue());

http://git-wip-us.apache.org/repos/asf/sqoop/blob/d69bd34e/common/src/main/java/org/apache/sqoop/model/MConfig.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/model/MConfig.java b/common/src/main/java/org/apache/sqoop/model/MConfig.java
index ad04263..484e05f 100644
--- a/common/src/main/java/org/apache/sqoop/model/MConfig.java
+++ b/common/src/main/java/org/apache/sqoop/model/MConfig.java
@@ -39,8 +39,8 @@ public final class MConfig extends MNamedElement implements MClonable {
   private Set<String> inputNames = new HashSet<String>();
   private Set<String> userOnlyEditableInputNames = new HashSet<String>();
 
-  public MConfig(String name, List<MInput<?>> inputs) {
-    super(name);
+  public MConfig(String name, List<MInput<?>> inputs, List<MValidator> mValidators) {
+    super(name, mValidators);
     this.inputs = inputs;
     if (inputs != null && inputs.size() > 0) {
       for (MInput<?> input : inputs) {
@@ -142,11 +142,11 @@ public final class MConfig extends MNamedElement implements MClonable {
 
   @Override
   public MConfig clone(boolean cloneWithValue) {
-    List<MInput<?>> copyInputs = new ArrayList<MInput<?>>();
+    List<MInput<?>> copyInputs = new ArrayList<>();
     for(MInput<?> itr : this.getInputs()) {
       copyInputs.add((MInput<?>)itr.clone(cloneWithValue));
     }
-    MConfig copyConfig = new MConfig(this.getName(), copyInputs);
+    MConfig copyConfig = new MConfig(this.getName(), copyInputs, getCloneOfValidators());
     return copyConfig;
   }
 }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/d69bd34e/common/src/main/java/org/apache/sqoop/model/MConfigList.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/model/MConfigList.java b/common/src/main/java/org/apache/sqoop/model/MConfigList.java
index 1d889ea..cf15777 100644
--- a/common/src/main/java/org/apache/sqoop/model/MConfigList.java
+++ b/common/src/main/java/org/apache/sqoop/model/MConfigList.java
@@ -34,7 +34,8 @@ public class MConfigList extends MValidatedElement implements MClonable {
   private final List<MConfig> configObjects;
   private final MConfigType type;
 
-  public MConfigList(List<MConfig> configObjects, MConfigType type) {
+  public MConfigList(List<MConfig> configObjects, MConfigType type, List<MValidator> mValidators) {
+    super(mValidators);
     this.configObjects = configObjects;
     this.type = type;
   }
@@ -144,7 +145,7 @@ public class MConfigList extends MValidatedElement implements MClonable {
         copyConfigs.add(newConfig);
       }
     }
-    MConfigList copyConfigList = new MConfigList(copyConfigs, type);
+    MConfigList copyConfigList = new MConfigList(copyConfigs, type, getCloneOfValidators());
     return copyConfigList;
   }
 }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/d69bd34e/common/src/main/java/org/apache/sqoop/model/MDateTimeInput.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/model/MDateTimeInput.java b/common/src/main/java/org/apache/sqoop/model/MDateTimeInput.java
index 7ce2558..7d282da 100644
--- a/common/src/main/java/org/apache/sqoop/model/MDateTimeInput.java
+++ b/common/src/main/java/org/apache/sqoop/model/MDateTimeInput.java
@@ -22,12 +22,14 @@ import org.joda.time.DateTime;
 import org.apache.sqoop.classification.InterfaceAudience;
 import org.apache.sqoop.classification.InterfaceStability;
 
+import java.util.List;
+
 @InterfaceAudience.Public
 @InterfaceStability.Unstable
 public class MDateTimeInput extends MInput<DateTime> {
 
-  public MDateTimeInput(String name, boolean sensitive, InputEditable editable, String overrides) {
-    super(name, sensitive, editable, overrides);
+  public MDateTimeInput(String name, boolean sensitive, InputEditable editable, String overrides, List<MValidator> mValidators) {
+    super(name, sensitive, editable, overrides, mValidators);
   }
 
   @Override
@@ -84,7 +86,7 @@ public class MDateTimeInput extends MInput<DateTime> {
 
   @Override
   public MDateTimeInput clone(boolean cloneWithValue) {
-    MDateTimeInput copy = new MDateTimeInput(getName(), isSensitive(), getEditable(), getOverrides());
+    MDateTimeInput copy = new MDateTimeInput(getName(), isSensitive(), getEditable(), getOverrides(), getCloneOfValidators());
     copy.setPersistenceId(getPersistenceId());
     if(cloneWithValue && this.getValue() != null) {
       copy.setValue(new DateTime(this.getValue()));

http://git-wip-us.apache.org/repos/asf/sqoop/blob/d69bd34e/common/src/main/java/org/apache/sqoop/model/MDriverConfig.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/model/MDriverConfig.java b/common/src/main/java/org/apache/sqoop/model/MDriverConfig.java
index 77d947f..2685296 100644
--- a/common/src/main/java/org/apache/sqoop/model/MDriverConfig.java
+++ b/common/src/main/java/org/apache/sqoop/model/MDriverConfig.java
@@ -30,8 +30,8 @@ import java.util.List;
 @InterfaceAudience.Public
 @InterfaceStability.Unstable
 public class MDriverConfig extends MConfigList {
-  public MDriverConfig(List<MConfig> configs) {
-    super(configs, MConfigType.JOB);
+  public MDriverConfig(List<MConfig> configs, List<MValidator> mValidators) {
+    super(configs, MConfigType.JOB, mValidators);
   }
 
   @Override
@@ -62,7 +62,7 @@ public class MDriverConfig extends MConfigList {
 
   @Override
   public MDriverConfig clone(boolean cloneWithValue) {
-    MDriverConfig copy = new MDriverConfig(super.clone(cloneWithValue).getConfigs());
+    MDriverConfig copy = new MDriverConfig(super.clone(cloneWithValue).getConfigs(), getCloneOfValidators());
     return copy;
   }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/sqoop/blob/d69bd34e/common/src/main/java/org/apache/sqoop/model/MEnumInput.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/model/MEnumInput.java b/common/src/main/java/org/apache/sqoop/model/MEnumInput.java
index df702f8..570269b 100644
--- a/common/src/main/java/org/apache/sqoop/model/MEnumInput.java
+++ b/common/src/main/java/org/apache/sqoop/model/MEnumInput.java
@@ -23,6 +23,7 @@ import org.apache.sqoop.classification.InterfaceStability;
 import org.apache.sqoop.common.SqoopException;
 
 import java.util.Arrays;
+import java.util.List;
 
 /**
  *
@@ -36,8 +37,8 @@ public class MEnumInput extends MInput<String> {
    */
   String []values;
 
-  public MEnumInput(String name, boolean sensitive, InputEditable editable, String overrides, String[] values) {
-    super(name, sensitive, editable, overrides);
+  public MEnumInput(String name, boolean sensitive, InputEditable editable, String overrides, String[] values, List<MValidator> mValidators) {
+    super(name, sensitive, editable, overrides, mValidators);
     if (values != null) {
       this.values = values.clone();
     } else {
@@ -139,7 +140,7 @@ public class MEnumInput extends MInput<String> {
   @Override
   public MEnumInput clone(boolean cloneWithValue) {
     MEnumInput copy = new MEnumInput(getName(), isSensitive(), getEditable(), getOverrides(),
-        getValues());
+        getValues(), getCloneOfValidators());
     copy.setPersistenceId(getPersistenceId());
     if(cloneWithValue) {
       copy.setValue(this.getValue());

http://git-wip-us.apache.org/repos/asf/sqoop/blob/d69bd34e/common/src/main/java/org/apache/sqoop/model/MFromConfig.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/model/MFromConfig.java b/common/src/main/java/org/apache/sqoop/model/MFromConfig.java
index 7093a93..3888d80 100644
--- a/common/src/main/java/org/apache/sqoop/model/MFromConfig.java
+++ b/common/src/main/java/org/apache/sqoop/model/MFromConfig.java
@@ -30,8 +30,8 @@ import java.util.List;
 @InterfaceAudience.Public
 @InterfaceStability.Unstable
 public class MFromConfig extends MConfigList {
-  public MFromConfig(List<MConfig> configs) {
-    super(configs, MConfigType.JOB);
+  public MFromConfig(List<MConfig> configs, List<MValidator> mValidators) {
+    super(configs, MConfigType.JOB, mValidators);
   }
 
   @Override
@@ -62,7 +62,7 @@ public class MFromConfig extends MConfigList {
 
   @Override
   public MFromConfig clone(boolean cloneWithValue) {
-    MFromConfig copy = new MFromConfig(super.clone(cloneWithValue).getConfigs());
+    MFromConfig copy = new MFromConfig(super.clone(cloneWithValue).getConfigs(), getCloneOfValidators());
     return copy;
   }
 }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/d69bd34e/common/src/main/java/org/apache/sqoop/model/MInput.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/model/MInput.java b/common/src/main/java/org/apache/sqoop/model/MInput.java
index 649f2fd..d3c69e9 100644
--- a/common/src/main/java/org/apache/sqoop/model/MInput.java
+++ b/common/src/main/java/org/apache/sqoop/model/MInput.java
@@ -20,6 +20,8 @@ package org.apache.sqoop.model;
 import org.apache.sqoop.classification.InterfaceAudience;
 import org.apache.sqoop.classification.InterfaceStability;
 
+import java.util.List;
+
 /**
  * Represents a parameter input used by the connector for creating a link
  * or a job object.
@@ -37,8 +39,8 @@ public abstract class MInput<T> extends MNamedElement implements MClonable {
 
   private T value;
 
-  protected MInput(String name, boolean sensitive, InputEditable editable, String overrides) {
-    super(name);
+  protected MInput(String name, boolean sensitive, InputEditable editable, String overrides, List<MValidator> mValidators) {
+    super(name, mValidators);
     this.sensitive = sensitive;
     this.editable = editable;
     this.overrides = overrides;

http://git-wip-us.apache.org/repos/asf/sqoop/blob/d69bd34e/common/src/main/java/org/apache/sqoop/model/MIntegerInput.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/model/MIntegerInput.java b/common/src/main/java/org/apache/sqoop/model/MIntegerInput.java
index 90b2d95..2a3ead8 100644
--- a/common/src/main/java/org/apache/sqoop/model/MIntegerInput.java
+++ b/common/src/main/java/org/apache/sqoop/model/MIntegerInput.java
@@ -20,6 +20,8 @@ package org.apache.sqoop.model;
 import org.apache.sqoop.classification.InterfaceAudience;
 import org.apache.sqoop.classification.InterfaceStability;
 
+import java.util.List;
+
 /**
  * Integer base user input.
  *
@@ -29,8 +31,8 @@ import org.apache.sqoop.classification.InterfaceStability;
 @InterfaceStability.Unstable
 public class MIntegerInput extends MInput<Integer> {
 
-  public MIntegerInput(String name, boolean sensitive, InputEditable editable, String overrides) {
-    super(name, sensitive, editable, overrides);
+  public MIntegerInput(String name, boolean sensitive, InputEditable editable, String overrides, List<MValidator> mValidators) {
+    super(name, sensitive, editable, overrides, mValidators);
   }
 
   @Override
@@ -87,7 +89,7 @@ public class MIntegerInput extends MInput<Integer> {
 
   @Override
   public MIntegerInput clone(boolean cloneWithValue) {
-    MIntegerInput copy = new MIntegerInput(getName(), isSensitive(), getEditable(), getOverrides());
+    MIntegerInput copy = new MIntegerInput(getName(), isSensitive(), getEditable(), getOverrides(), getCloneOfValidators());
     copy.setPersistenceId(getPersistenceId());
     if(cloneWithValue) {
       copy.setValue(this.getValue());

http://git-wip-us.apache.org/repos/asf/sqoop/blob/d69bd34e/common/src/main/java/org/apache/sqoop/model/MLinkConfig.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/model/MLinkConfig.java b/common/src/main/java/org/apache/sqoop/model/MLinkConfig.java
index 6b33fdc..8edb3c7 100644
--- a/common/src/main/java/org/apache/sqoop/model/MLinkConfig.java
+++ b/common/src/main/java/org/apache/sqoop/model/MLinkConfig.java
@@ -31,8 +31,8 @@ import java.util.List;
 @InterfaceStability.Unstable
 public class MLinkConfig extends MConfigList {
 
-  public MLinkConfig(List<MConfig> configs) {
-    super(configs, MConfigType.LINK);
+  public MLinkConfig(List<MConfig> configs, List<MValidator> mValidators) {
+    super(configs, MConfigType.LINK, mValidators);
   }
 
   @Override
@@ -44,7 +44,7 @@ public class MLinkConfig extends MConfigList {
 
   @Override
   public MLinkConfig clone(boolean cloneWithValue) {
-    MLinkConfig copy = new MLinkConfig(super.clone(cloneWithValue).getConfigs());
+    MLinkConfig copy = new MLinkConfig(super.clone(cloneWithValue).getConfigs(), getCloneOfValidators());
     return copy;
   }
 }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/d69bd34e/common/src/main/java/org/apache/sqoop/model/MListInput.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/model/MListInput.java b/common/src/main/java/org/apache/sqoop/model/MListInput.java
index 04dbaf2..2fd9fd8 100644
--- a/common/src/main/java/org/apache/sqoop/model/MListInput.java
+++ b/common/src/main/java/org/apache/sqoop/model/MListInput.java
@@ -28,8 +28,8 @@ import org.apache.sqoop.utils.UrlSafeUtils;
 @InterfaceStability.Unstable
 public class MListInput extends MInput<List<String>> {
 
-  public MListInput(String name, boolean sensitive, InputEditable editable, String overrides) {
-    super(name, sensitive, editable, overrides);
+  public MListInput(String name, boolean sensitive, InputEditable editable, String overrides, List<MValidator> mValidators) {
+    super(name, sensitive, editable, overrides, mValidators);
   }
 
   @Override
@@ -102,7 +102,7 @@ public class MListInput extends MInput<List<String>> {
 
   @Override
   public Object clone(boolean cloneWithValue) {
-    MListInput copy = new MListInput(getName(), isSensitive(), getEditable(), getOverrides());
+    MListInput copy = new MListInput(getName(), isSensitive(), getEditable(), getOverrides(), getCloneOfValidators());
     copy.setPersistenceId(getPersistenceId());
     if(cloneWithValue && this.getValue() != null) {
       List<String> copyList = new LinkedList<String>();

http://git-wip-us.apache.org/repos/asf/sqoop/blob/d69bd34e/common/src/main/java/org/apache/sqoop/model/MLongInput.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/model/MLongInput.java b/common/src/main/java/org/apache/sqoop/model/MLongInput.java
index eb2c277..82d3ede 100644
--- a/common/src/main/java/org/apache/sqoop/model/MLongInput.java
+++ b/common/src/main/java/org/apache/sqoop/model/MLongInput.java
@@ -20,6 +20,8 @@ package org.apache.sqoop.model;
 import org.apache.sqoop.classification.InterfaceAudience;
 import org.apache.sqoop.classification.InterfaceStability;
 
+import java.util.List;
+
 /**
  * Long user input.
  *
@@ -28,8 +30,8 @@ import org.apache.sqoop.classification.InterfaceStability;
 @InterfaceStability.Unstable
 public class MLongInput extends MInput<Long> {
 
-  public MLongInput(String name, boolean sensitive, InputEditable editable, String overrides) {
-    super(name, sensitive, editable, overrides);
+  public MLongInput(String name, boolean sensitive, InputEditable editable, String overrides, List<MValidator> mValidators) {
+    super(name, sensitive, editable, overrides, mValidators);
   }
 
   @Override
@@ -86,7 +88,7 @@ public class MLongInput extends MInput<Long> {
 
   @Override
   public MLongInput clone(boolean cloneWithValue) {
-    MLongInput copy = new MLongInput(getName(), isSensitive(), getEditable(), getOverrides());
+    MLongInput copy = new MLongInput(getName(), isSensitive(), getEditable(), getOverrides(), getCloneOfValidators());
     copy.setPersistenceId(getPersistenceId());
     if(cloneWithValue) {
       copy.setValue(this.getValue());

http://git-wip-us.apache.org/repos/asf/sqoop/blob/d69bd34e/common/src/main/java/org/apache/sqoop/model/MMapInput.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/model/MMapInput.java b/common/src/main/java/org/apache/sqoop/model/MMapInput.java
index 4e8df34..2fb4e02 100644
--- a/common/src/main/java/org/apache/sqoop/model/MMapInput.java
+++ b/common/src/main/java/org/apache/sqoop/model/MMapInput.java
@@ -18,6 +18,7 @@
 package org.apache.sqoop.model;
 
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.regex.Pattern;
@@ -35,8 +36,8 @@ public final class MMapInput extends MInput<Map<String, String>> {
 
   private final String sensitiveKeyPattern;
 
-  public MMapInput(String name, boolean sensitive, InputEditable editable, String overrides, String sensitiveKeyPattern) {
-    super(name, sensitive, editable, overrides);
+  public MMapInput(String name, boolean sensitive, InputEditable editable, String overrides, String sensitiveKeyPattern, List<MValidator> mValidators) {
+    super(name, sensitive, editable, overrides, mValidators);
     this.sensitiveKeyPattern = sensitiveKeyPattern;
   }
 
@@ -124,7 +125,7 @@ public final class MMapInput extends MInput<Map<String, String>> {
 
   @Override
   public MMapInput clone(boolean cloneWithValue) {
-    MMapInput copy = new MMapInput(getName(), isSensitive(), getEditable(), getOverrides(), getSensitiveKeyPattern());
+    MMapInput copy = new MMapInput(getName(), isSensitive(), getEditable(), getOverrides(), getSensitiveKeyPattern(), getCloneOfValidators());
     copy.setPersistenceId(getPersistenceId());
     if(cloneWithValue && this.getValue() != null) {
       Map<String, String> copyMap = new HashMap<String, String>();

http://git-wip-us.apache.org/repos/asf/sqoop/blob/d69bd34e/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 7972467..2e4dab3 100644
--- a/common/src/main/java/org/apache/sqoop/model/MNamedElement.java
+++ b/common/src/main/java/org/apache/sqoop/model/MNamedElement.java
@@ -20,6 +20,8 @@ package org.apache.sqoop.model;
 import org.apache.sqoop.classification.InterfaceAudience;
 import org.apache.sqoop.classification.InterfaceStability;
 
+import java.util.List;
+
 /**
  * Represents an element of metadata used by the connector.
  */
@@ -33,12 +35,13 @@ public abstract class MNamedElement extends MValidatedElement {
   private String labelKey;
   private String helpKey;
 
-  protected MNamedElement(String name) {
+  protected MNamedElement(String name, List<MValidator> mValidators) {
+    super(mValidators);
     setName(name);
   }
 
   protected MNamedElement(MNamedElement other) {
-    this(other.name);
+    this(other.name, other.getCloneOfValidators());
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/sqoop/blob/d69bd34e/common/src/main/java/org/apache/sqoop/model/MStringInput.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/model/MStringInput.java b/common/src/main/java/org/apache/sqoop/model/MStringInput.java
index 7365098..5ab902d 100644
--- a/common/src/main/java/org/apache/sqoop/model/MStringInput.java
+++ b/common/src/main/java/org/apache/sqoop/model/MStringInput.java
@@ -21,6 +21,8 @@ import org.apache.sqoop.classification.InterfaceAudience;
 import org.apache.sqoop.classification.InterfaceStability;
 import org.apache.sqoop.utils.UrlSafeUtils;
 
+import java.util.List;
+
 /**
  * Represents a <tt>String</tt> input. The boolean flag <tt>sensitive</tt> supplied
  * to its constructor can be used to indicate if the string should be masked
@@ -38,8 +40,8 @@ public final class MStringInput extends MInput<String> {
    * @param sensitive a flag indicating if the string should be masked
    * @param maxLength the maximum length of the string
    */
-  public MStringInput(String name, boolean sensitive, InputEditable editable, String overrides, short maxLength) {
-    super(name, sensitive, editable, overrides);
+  public MStringInput(String name, boolean sensitive, InputEditable editable, String overrides, short maxLength, List<MValidator> mValidators) {
+    super(name, sensitive, editable, overrides, mValidators);
     this.maxLength = maxLength;
   }
 
@@ -112,7 +114,7 @@ public final class MStringInput extends MInput<String> {
   @Override
   public MStringInput clone(boolean cloneWithValue) {
     MStringInput copy = new MStringInput(getName(), isSensitive(), getEditable(), getOverrides(),
-        getMaxLength());
+        getMaxLength(), getCloneOfValidators());
     copy.setPersistenceId(getPersistenceId());
     if(cloneWithValue) {
       copy.setValue(this.getValue());

http://git-wip-us.apache.org/repos/asf/sqoop/blob/d69bd34e/common/src/main/java/org/apache/sqoop/model/MToConfig.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/model/MToConfig.java b/common/src/main/java/org/apache/sqoop/model/MToConfig.java
index eff533f..6f1a0f2 100644
--- a/common/src/main/java/org/apache/sqoop/model/MToConfig.java
+++ b/common/src/main/java/org/apache/sqoop/model/MToConfig.java
@@ -30,8 +30,8 @@ import java.util.List;
 @InterfaceAudience.Public
 @InterfaceStability.Unstable
 public class MToConfig extends MConfigList {
-  public MToConfig(List<MConfig> configs) {
-    super(configs, MConfigType.JOB);
+  public MToConfig(List<MConfig> configs, List<MValidator> mValidators) {
+    super(configs, MConfigType.JOB, mValidators);
   }
 
   @Override
@@ -62,7 +62,7 @@ public class MToConfig extends MConfigList {
 
   @Override
   public MToConfig clone(boolean cloneWithValue) {
-    MToConfig copy = new MToConfig(super.clone(cloneWithValue).getConfigs());
+    MToConfig copy = new MToConfig(super.clone(cloneWithValue).getConfigs(), getCloneOfValidators());
     return copy;
   }
 }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/d69bd34e/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 c8042f6..b2913f1 100644
--- a/common/src/main/java/org/apache/sqoop/model/MValidatedElement.java
+++ b/common/src/main/java/org/apache/sqoop/model/MValidatedElement.java
@@ -22,6 +22,7 @@ import org.apache.sqoop.classification.InterfaceStability;
 import org.apache.sqoop.validation.Message;
 import org.apache.sqoop.validation.Status;
 
+import java.util.ArrayList;
 import java.util.LinkedList;
 import java.util.List;
 
@@ -32,6 +33,8 @@ import java.util.List;
 @InterfaceStability.Unstable
 public abstract class MValidatedElement extends MPersistableEntity {
 
+  private List<MValidator> mValidators;
+
   /**
    * Validation messages.
    */
@@ -42,13 +45,15 @@ public abstract class MValidatedElement extends MPersistableEntity {
    */
   private Status validationStatus;
 
-  public MValidatedElement() {
+  public MValidatedElement(List<MValidator> mValidators) {
+    this.mValidators = mValidators;
     resetValidationMessages();
   }
 
   public MValidatedElement(MValidatedElement other) {
     super(other);
     resetValidationMessages();
+    this.mValidators = other.getCloneOfValidators();
     this.validationStatus = other.validationStatus;
     this.validationMessages.addAll(other.validationMessages);
   }
@@ -97,6 +102,10 @@ public abstract class MValidatedElement extends MPersistableEntity {
     return this.validationMessages;
   }
 
+  public List<MValidator> getValidators() {
+    return mValidators;
+  }
+
   /**
    * Return message validation status.
    */
@@ -104,4 +113,14 @@ public abstract class MValidatedElement extends MPersistableEntity {
     return validationStatus;
   }
 
+  public List<MValidator> getCloneOfValidators() {
+    if (getValidators() == null) return null;
+
+    List<MValidator> copyValidators = new ArrayList<>();
+    for(MValidator itr : this.getValidators()) {
+      copyValidators.add((MValidator)itr.clone(true));
+    }
+    return copyValidators;
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/d69bd34e/common/src/main/java/org/apache/sqoop/model/MValidator.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/model/MValidator.java b/common/src/main/java/org/apache/sqoop/model/MValidator.java
new file mode 100644
index 0000000..555cb5b
--- /dev/null
+++ b/common/src/main/java/org/apache/sqoop/model/MValidator.java
@@ -0,0 +1,68 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sqoop.model;
+
+import org.apache.sqoop.classification.InterfaceAudience;
+import org.apache.sqoop.classification.InterfaceStability;
+
+/**
+ * Represents an @Validator class by its name and optional argument
+ */
+@InterfaceAudience.Public
+@InterfaceStability.Unstable
+public class MValidator implements MClonable {
+  private final String validatorClass;
+  private final String strArg;
+
+  public MValidator(String validatorClass, String strArg) {
+    this.validatorClass = validatorClass;
+    this.strArg = strArg;
+  }
+
+  // The value of cloneWithValue is ignored
+  @Override
+  public Object clone(boolean cloneWithValue) {
+    return new MValidator(validatorClass, strArg);
+  }
+
+  public String getValidatorClass() {
+    return validatorClass;
+  }
+
+  public String getStrArg() {
+    return strArg;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (!(o instanceof MValidator)) return false;
+
+    MValidator that = (MValidator) o;
+
+    if (!getValidatorClass().equals(that.getValidatorClass())) return false;
+    return getStrArg().equals(that.getStrArg());
+  }
+
+  @Override
+  public int hashCode() {
+    int result = getValidatorClass().hashCode();
+    result = 31 * result + getStrArg().hashCode();
+    return result;
+  }
+}

http://git-wip-us.apache.org/repos/asf/sqoop/blob/d69bd34e/common/src/test/java/org/apache/sqoop/json/TestLinkBean.java
----------------------------------------------------------------------
diff --git a/common/src/test/java/org/apache/sqoop/json/TestLinkBean.java b/common/src/test/java/org/apache/sqoop/json/TestLinkBean.java
index 59d900f..0df0f9d 100644
--- a/common/src/test/java/org/apache/sqoop/json/TestLinkBean.java
+++ b/common/src/test/java/org/apache/sqoop/json/TestLinkBean.java
@@ -17,16 +17,19 @@
  */
 package org.apache.sqoop.json;
 
+import static org.apache.sqoop.json.util.ConfigInputSerialization.restoreValidator;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertFalse;
 import static org.testng.Assert.assertTrue;
 
 import java.util.Date;
+import java.util.List;
 
 import org.apache.sqoop.json.util.BeanTestUtil;
 import org.apache.sqoop.json.util.ConfigInputConstants;
 import org.apache.sqoop.model.MLink;
 import org.apache.sqoop.model.MStringInput;
+import org.apache.sqoop.model.MValidator;
 import org.json.simple.JSONArray;
 import org.json.simple.JSONObject;
 import org.testng.annotations.Test;
@@ -50,7 +53,13 @@ public class TestLinkBean {
 
     // Check for sensitivity
     JSONObject linkObj = (JSONObject) json.get(LinkBean.LINK);
-    JSONArray linkConfigs = (JSONArray) linkObj.get(LinkBean.LINK_CONFIG_VALUES);
+    JSONObject linkConfigList = (JSONObject) linkObj.get(LinkBean.LINK_CONFIG_VALUES);
+    JSONArray linkConfigs = (JSONArray) linkConfigList.get(ConfigInputConstants.CONFIGS);
+    List<MValidator> linkValidators = restoreValidator((JSONArray)
+      linkConfigList.get(ConfigInputConstants.CONFIG_VALIDATORS));
+    MValidator mValidator = linkValidators.get(0);
+    assertEquals("testValidator1", mValidator.getValidatorClass());
+    assertEquals("", mValidator.getStrArg());
     JSONObject linkConfig = (JSONObject) linkConfigs.get(0);
     JSONArray inputs = (JSONArray) linkConfig.get(ConfigInputConstants.CONFIG_INPUTS);
     for (Object in : inputs) {
@@ -100,8 +109,9 @@ public class TestLinkBean {
 
     // Sensitive values should exist
     JSONObject linkObj = (JSONObject) json.get(LinkBean.LINK);
-    JSONArray linkConfigsObj = (JSONArray) linkObj.get(LinkBean.LINK_CONFIG_VALUES);
-    JSONObject linkConfigObj = (JSONObject) linkConfigsObj.get(0);
+    JSONObject linkConfigList = (JSONObject) linkObj.get(LinkBean.LINK_CONFIG_VALUES);
+    JSONArray linkConfigs = (JSONArray) linkConfigList.get(ConfigInputConstants.CONFIGS);
+    JSONObject linkConfigObj = (JSONObject) linkConfigs.get(0);
     JSONArray inputs = (JSONArray) linkConfigObj.get(ConfigInputConstants.CONFIG_INPUTS);
     assertEquals(3, inputs.size());
     // Inputs are ordered when creating link
@@ -110,8 +120,9 @@ public class TestLinkBean {
 
     // Sensitive values should not exist
     linkObj = (JSONObject) jsonFiltered.get(LinkBean.LINK);
-    linkConfigsObj = (JSONArray) linkObj.get(LinkBean.LINK_CONFIG_VALUES);
-    linkConfigObj = (JSONObject) linkConfigsObj.get(0);
+    linkConfigList = (JSONObject) linkObj.get(LinkBean.LINK_CONFIG_VALUES);
+    linkConfigs = (JSONArray) linkConfigList.get(ConfigInputConstants.CONFIGS);
+    linkConfigObj = (JSONObject) linkConfigs.get(0);
     inputs = (JSONArray) linkConfigObj.get(ConfigInputConstants.CONFIG_INPUTS);
     assertEquals(3, inputs.size());
     // Inputs are ordered when creating link

http://git-wip-us.apache.org/repos/asf/sqoop/blob/d69bd34e/common/src/test/java/org/apache/sqoop/json/TestLinksBean.java
----------------------------------------------------------------------
diff --git a/common/src/test/java/org/apache/sqoop/json/TestLinksBean.java b/common/src/test/java/org/apache/sqoop/json/TestLinksBean.java
index 7faab88..0ee29fa 100644
--- a/common/src/test/java/org/apache/sqoop/json/TestLinksBean.java
+++ b/common/src/test/java/org/apache/sqoop/json/TestLinksBean.java
@@ -58,7 +58,8 @@ public class TestLinksBean {
     JSONArray linksObj = (JSONArray) json.get(LinksBean.LINKS);
     JSONObject linkObj = (JSONObject) linksObj.get(0);
 
-    JSONArray linkConfigs = (JSONArray) linkObj.get(LinkBean.LINK_CONFIG_VALUES);
+    JSONObject linkConfigList = (JSONObject) linkObj.get(LinkBean.LINK_CONFIG_VALUES);
+    JSONArray linkConfigs = (JSONArray) linkConfigList.get(ConfigInputConstants.CONFIGS);
     JSONObject linkConfig = (JSONObject) linkConfigs.get(0);
     JSONArray inputs = (JSONArray) linkConfig.get(ConfigInputConstants.CONFIG_INPUTS);
     for (Object inp : inputs) {

http://git-wip-us.apache.org/repos/asf/sqoop/blob/d69bd34e/common/src/test/java/org/apache/sqoop/json/util/BeanTestUtil.java
----------------------------------------------------------------------
diff --git a/common/src/test/java/org/apache/sqoop/json/util/BeanTestUtil.java b/common/src/test/java/org/apache/sqoop/json/util/BeanTestUtil.java
index ba69de6..51ab0e5 100644
--- a/common/src/test/java/org/apache/sqoop/json/util/BeanTestUtil.java
+++ b/common/src/test/java/org/apache/sqoop/json/util/BeanTestUtil.java
@@ -24,6 +24,7 @@ import org.apache.sqoop.model.MFromConfig;
 import org.apache.sqoop.model.MJob;
 import org.apache.sqoop.model.MLink;
 import org.apache.sqoop.model.MToConfig;
+import org.apache.sqoop.model.MValidator;
 
 public class BeanTestUtil {
 

http://git-wip-us.apache.org/repos/asf/sqoop/blob/d69bd34e/common/src/test/java/org/apache/sqoop/json/util/ConfigTestUtil.java
----------------------------------------------------------------------
diff --git a/common/src/test/java/org/apache/sqoop/json/util/ConfigTestUtil.java b/common/src/test/java/org/apache/sqoop/json/util/ConfigTestUtil.java
index fbc7faa..f5373eb 100644
--- a/common/src/test/java/org/apache/sqoop/json/util/ConfigTestUtil.java
+++ b/common/src/test/java/org/apache/sqoop/json/util/ConfigTestUtil.java
@@ -18,6 +18,7 @@
 package org.apache.sqoop.json.util;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -33,6 +34,7 @@ import org.apache.sqoop.model.MIntegerInput;
 import org.apache.sqoop.model.MLinkConfig;
 import org.apache.sqoop.model.MStringInput;
 import org.apache.sqoop.model.MToConfig;
+import org.apache.sqoop.model.MValidator;
 import org.apache.sqoop.utils.MapResourceBundle;
 
 public class ConfigTestUtil {
@@ -44,18 +46,24 @@ public class ConfigTestUtil {
     List<MConfig> driverConfigs = new ArrayList<MConfig>();
     inputs = new ArrayList<MInput<?>>();
 
-    input = new MIntegerInput("numExtractors", false, InputEditable.ANY, StringUtils.EMPTY);
+    input = new MIntegerInput("numExtractors", false, InputEditable.ANY, StringUtils.EMPTY, Collections.EMPTY_LIST);
     input.setPersistenceId(1);
     inputs.add(input);
 
-    input = new MIntegerInput("numLoaders", false, InputEditable.USER_ONLY, StringUtils.EMPTY);
+    input = new MIntegerInput("numLoaders", false, InputEditable.USER_ONLY, StringUtils.EMPTY, Collections.EMPTY_LIST);
     input.setPersistenceId(2);
     inputs.add(input);
 
-    config = new MConfig("driver", inputs);
+    config = new MConfig("driver", inputs, Collections.EMPTY_LIST);
     config.setPersistenceId(10);
     driverConfigs.add(config);
-    return new MDriverConfig(driverConfigs);
+
+
+    List<MValidator> validators = new ArrayList<>();
+    validators.add(new MValidator("testValidator1", ""));
+    validators.add(new MValidator("testValidator2", "blah"));
+
+    return new MDriverConfig(driverConfigs, validators);
   }
 
   public static MLinkConfig getLinkConfig() {
@@ -65,25 +73,28 @@ public class ConfigTestUtil {
     List<MConfig> linkConfig = new ArrayList<MConfig>();
     inputs = new ArrayList<MInput<?>>();
 
-    input = new MStringInput("url", false, InputEditable.USER_ONLY, StringUtils.EMPTY, (short) 10);
+    input = new MStringInput("url", false, InputEditable.USER_ONLY, StringUtils.EMPTY, (short) 10, Collections.EMPTY_LIST);
     input.setPersistenceId(1);
     inputs.add(input);
 
-    input = new MStringInput("username", false, InputEditable.USER_ONLY, "password", (short) 10);
+    input = new MStringInput("username", false, InputEditable.USER_ONLY, "password", (short) 10, Collections.EMPTY_LIST);
     input.setPersistenceId(2);
     input.setValue("test");
     inputs.add(input);
 
-    input = new MStringInput("password", true, InputEditable.USER_ONLY, StringUtils.EMPTY, (short) 10);
+    input = new MStringInput("password", true, InputEditable.USER_ONLY, StringUtils.EMPTY, (short) 10, Collections.EMPTY_LIST);
     input.setPersistenceId(3);
     input.setValue("test");
     inputs.add(input);
 
-    config = new MConfig("connection", inputs);
+    config = new MConfig("connection", inputs, Collections.EMPTY_LIST);
     config.setPersistenceId(10);
     linkConfig.add(config);
 
-    return new MLinkConfig(linkConfig);
+    List<MValidator> validators = new ArrayList<>();
+    validators.add(new MValidator("testValidator1", ""));
+
+    return new MLinkConfig(linkConfig, validators);
   }
 
   static MFromConfig getFromConfig() {
@@ -94,41 +105,43 @@ public class ConfigTestUtil {
 
     inputs = new ArrayList<MInput<?>>();
 
-    input = new MStringInput("A", false, InputEditable.USER_ONLY, StringUtils.EMPTY, (short) 10);
+    input = new MStringInput("A", false, InputEditable.USER_ONLY, StringUtils.EMPTY, (short) 10, Collections.EMPTY_LIST);
     input.setPersistenceId(4);
     inputs.add(input);
 
-    input = new MStringInput("B", false, InputEditable.USER_ONLY, StringUtils.EMPTY, (short) 10);
+    input = new MStringInput("B", false, InputEditable.USER_ONLY, StringUtils.EMPTY, (short) 10, Collections.EMPTY_LIST);
     input.setPersistenceId(5);
     inputs.add(input);
 
-    input = new MStringInput("C", false, InputEditable.USER_ONLY, StringUtils.EMPTY, (short) 10);
+    input = new MStringInput("C", false, InputEditable.USER_ONLY, StringUtils.EMPTY, (short) 10, Collections.EMPTY_LIST);
     input.setPersistenceId(6);
     inputs.add(input);
 
-    config = new MConfig("Z", inputs);
+    config = new MConfig("Z", inputs, Collections.EMPTY_LIST);
     config.setPersistenceId(11);
  jobConfigs.add(config);
 
     inputs = new ArrayList<MInput<?>>();
 
-    input = new MStringInput("D", false, InputEditable.USER_ONLY, StringUtils.EMPTY, (short) 10);
+    input = new MStringInput("D", false, InputEditable.USER_ONLY, StringUtils.EMPTY, (short) 10, Collections.EMPTY_LIST);
     input.setPersistenceId(7);
     inputs.add(input);
 
-    input = new MStringInput("E", false, InputEditable.USER_ONLY, "D, F", (short) 10);
+    input = new MStringInput("E", false, InputEditable.USER_ONLY, "D, F", (short) 10, Collections.EMPTY_LIST);
     input.setPersistenceId(8);
     inputs.add(input);
 
-    input = new MStringInput("F", false, InputEditable.USER_ONLY, StringUtils.EMPTY, (short) 10);
+    input = new MStringInput("F", false, InputEditable.USER_ONLY, StringUtils.EMPTY, (short) 10, Collections.EMPTY_LIST);
     input.setPersistenceId(9);
     inputs.add(input);
 
-    config = new MConfig("from-table", inputs);
+    config = new MConfig("from-table", inputs, Collections.EMPTY_LIST);
     config.setPersistenceId(12);
     jobConfigs.add(config);
 
-    return new MFromConfig(jobConfigs);
+    List<MValidator> validators = new ArrayList<>();
+
+    return new MFromConfig(jobConfigs, validators);
   }
 
   static MToConfig getToConfig() {
@@ -139,41 +152,45 @@ public class ConfigTestUtil {
 
     inputs = new ArrayList<MInput<?>>();
 
-    input = new MStringInput("A", false, InputEditable.ANY, StringUtils.EMPTY, (short) 10);
+    input = new MStringInput("A", false, InputEditable.ANY, StringUtils.EMPTY, (short) 10, Collections.EMPTY_LIST);
     input.setPersistenceId(4);
     inputs.add(input);
 
-    input = new MStringInput("B", false, InputEditable.ANY, StringUtils.EMPTY, (short) 10);
+    input = new MStringInput("B", false, InputEditable.ANY, StringUtils.EMPTY, (short) 10, Collections.EMPTY_LIST);
     input.setPersistenceId(5);
     inputs.add(input);
 
-    input = new MStringInput("C", false, InputEditable.ANY, StringUtils.EMPTY, (short) 10);
+    input = new MStringInput("C", false, InputEditable.ANY, StringUtils.EMPTY, (short) 10, Collections.EMPTY_LIST);
     input.setPersistenceId(6);
     inputs.add(input);
 
-    config = new MConfig("Z", inputs);
+    config = new MConfig("Z", inputs, Collections.EMPTY_LIST);
     config.setPersistenceId(11);
     jobConfigs.add(config);
 
     inputs = new ArrayList<MInput<?>>();
 
-    input = new MStringInput("D", false, InputEditable.ANY, StringUtils.EMPTY, (short) 10);
+    input = new MStringInput("D", false, InputEditable.ANY, StringUtils.EMPTY, (short) 10, Collections.EMPTY_LIST);
     input.setPersistenceId(7);
     inputs.add(input);
 
-    input = new MStringInput("E", false, InputEditable.ANY, StringUtils.EMPTY, (short) 10);
+    input = new MStringInput("E", false, InputEditable.ANY, StringUtils.EMPTY, (short) 10, Collections.EMPTY_LIST);
     input.setPersistenceId(8);
     inputs.add(input);
 
-    input = new MStringInput("F", false, InputEditable.ANY, StringUtils.EMPTY, (short) 10);
+    input = new MStringInput("F", false, InputEditable.ANY, StringUtils.EMPTY, (short) 10, Collections.EMPTY_LIST);
     input.setPersistenceId(9);
  inputs.add(input);
 
-    config = new MConfig("to-table", inputs);
+    config = new MConfig("to-table", inputs, Collections.EMPTY_LIST);
     config.setPersistenceId(12);
     jobConfigs.add(config);
 
-    return new MToConfig(jobConfigs);
+    List<MValidator> validators = new ArrayList<>();
+    validators.add(new MValidator("testValidator1", ""));
+    validators.add(new MValidator("testValidator2", "blah"));
+
+    return new MToConfig(jobConfigs, validators);
   }
 
   public static ResourceBundle getResourceBundle() {


Mime
View raw message