http://git-wip-us.apache.org/repos/asf/sqoop/blob/8362c73c/common/src/main/java/org/apache/sqoop/model/MConnector.java ---------------------------------------------------------------------- diff --git a/common/src/main/java/org/apache/sqoop/model/MConnector.java b/common/src/main/java/org/apache/sqoop/model/MConnector.java index 7999b08..2f42191 100644 --- a/common/src/main/java/org/apache/sqoop/model/MConnector.java +++ b/common/src/main/java/org/apache/sqoop/model/MConnector.java @@ -23,28 +23,27 @@ import org.apache.sqoop.common.SqoopException; import org.apache.sqoop.common.SupportedDirections; /** - * Connector metadata. - * - * Includes unique id that identifies connector in metadata store, unique human - * readable name, corresponding name and all forms for all supported job types. + * Connector entity supports the FROM/TO {@link Transferable} Includes unique id + * that identifies connector in the repository, unique human readable name, + * corresponding name and all configs to support the from and to data sources */ public final class MConnector extends MPersistableEntity implements MClonable { private final String uniqueName; private final String className; - private final MConnectionForms connectionForms; - private final MJobForms fromJobForms; - private final MJobForms toJobForms; - String version; - - public MConnector(String uniqueName, String className, - String version, MConnectionForms connectionForms, - MJobForms fromJobForms, MJobForms toJobForms) { + private final String version; + private final MLinkConfig linkConfig; + private final MFromConfig fromConfig; + private final MToConfig toConfig; + + public MConnector(String uniqueName, String className, String version, MLinkConfig linkConfig, + MFromConfig fromConfig, MToConfig toConfig) { this.version = version; - this.connectionForms = connectionForms; - this.fromJobForms = fromJobForms; - this.toJobForms = toJobForms; + this.linkConfig = linkConfig; + this.fromConfig = fromConfig; + this.toConfig = toConfig; + // Why are we abusing NPE? if (uniqueName == null || className == null) { throw new NullPointerException(); } @@ -63,17 +62,15 @@ public final class MConnector extends MPersistableEntity implements MClonable { @Override public String toString() { - MJobForms fromJobForms = this.getJobForms(Direction.FROM); - MJobForms toJobForms = this.getJobForms(Direction.TO); StringBuilder sb = new StringBuilder("connector-"); sb.append(uniqueName).append(":").append(getPersistenceId()).append(":"); sb.append(className); - sb.append(", ").append(getConnectionForms().toString()); - if (fromJobForms != null) { - sb.append(", ").append(fromJobForms.toString()); + sb.append(", ").append(getLinkConfig().toString()); + if (getConfig(Direction.FROM) != null) { + sb.append(", ").append(getConfig(Direction.FROM).toString()); } - if (toJobForms != null) { - sb.append(", ").append(toJobForms.toString()); + if (getConfig(Direction.TO) != null) { + sb.append(", ").append(getConfig(Direction.TO).toString()); } return sb.toString(); } @@ -94,41 +91,39 @@ public final class MConnector extends MPersistableEntity implements MClonable { if (supportedDirections.isDirectionSupported(Direction.FROM) && mcSupportedDirections.isDirectionSupported(Direction.FROM) - && !getJobForms(Direction.FROM).equals(mc.getJobForms(Direction.FROM))) { + && !getFromConfig().equals(mc.getFromConfig())) { return false; } - if (supportedDirections.isDirectionSupported(Direction.FROM) - != mcSupportedDirections.isDirectionSupported(Direction.FROM)) { + if (supportedDirections.isDirectionSupported(Direction.FROM) != mcSupportedDirections + .isDirectionSupported(Direction.FROM)) { return false; } if (supportedDirections.isDirectionSupported(Direction.TO) && mcSupportedDirections.isDirectionSupported(Direction.TO) - && !getJobForms(Direction.TO).equals(mc.getJobForms(Direction.TO))) { + && !getToConfig().equals(mc.getToConfig())) { return false; } - if (supportedDirections.isDirectionSupported(Direction.TO) - != mcSupportedDirections.isDirectionSupported(Direction.TO)) { + if (supportedDirections.isDirectionSupported(Direction.TO) != mcSupportedDirections + .isDirectionSupported(Direction.TO)) { return false; } - return uniqueName.equals(mc.uniqueName) - && className.equals(mc.className) - && version.equals(mc.version) - && connectionForms.equals(mc.getConnectionForms()); + return uniqueName.equals(mc.uniqueName) && className.equals(mc.className) + && version.equals(mc.version) && linkConfig.equals((mc.getLinkConfig())); } @Override public int hashCode() { SupportedDirections supportedDirections = getSupportedDirections(); - int result = getConnectionForms().hashCode(); + int result = getLinkConfig().hashCode(); if (supportedDirections.isDirectionSupported(Direction.FROM)) { - result = 31 * result + getJobForms(Direction.FROM).hashCode(); + result = 31 * result + getFromConfig().hashCode(); } if (supportedDirections.isDirectionSupported(Direction.TO)) { - result = 31 * result + getJobForms(Direction.TO).hashCode(); + result = 31 * result + getToConfig().hashCode(); } result = 31 * result + version.hashCode(); result = 31 * result + uniqueName.hashCode(); @@ -137,58 +132,57 @@ public final class MConnector extends MPersistableEntity implements MClonable { } public MConnector clone(boolean cloneWithValue) { - //Connector never have any values filled + // Connector never have any values filled cloneWithValue = false; - MJobForms fromJobForms = this.getJobForms(Direction.FROM); - MJobForms toJobForms = this.getJobForms(Direction.TO); + MFromConfig fromConfig = this.getFromConfig(); + MToConfig toConfig = this.getToConfig(); - if (fromJobForms != null) { - fromJobForms = fromJobForms.clone(cloneWithValue); + if (fromConfig != null) { + fromConfig = fromConfig.clone(cloneWithValue); } - if (toJobForms != null) { - toJobForms = toJobForms.clone(cloneWithValue); + if (toConfig != null) { + toConfig = toConfig.clone(cloneWithValue); } - MConnector copy = new MConnector( - this.getUniqueName(), - this.getClassName(), - this.getVersion(), - this.getConnectionForms().clone(cloneWithValue), - fromJobForms, - toJobForms); + MConnector copy = new MConnector(this.getUniqueName(), this.getClassName(), this.getVersion(), + this.getLinkConfig().clone(cloneWithValue), fromConfig, toConfig); copy.setPersistenceId(this.getPersistenceId()); return copy; } - public MConnectionForms getConnectionForms() { - return connectionForms; + public MLinkConfig getLinkConfig() { + return linkConfig; } - public MJobForms getJobForms(Direction type) { - switch(type) { - case FROM: - return fromJobForms; + public MConfigList getConfig(Direction type) { + switch (type) { + case FROM: + return fromConfig; - case TO: - return toJobForms; + case TO: + return toConfig; - default: - throw new SqoopException(DirectionError.DIRECTION_0000, "Direction: " + type); + default: + throw new SqoopException(DirectionError.DIRECTION_0000, "Direction: " + type); } } - public String getVersion() { - return version; + public MFromConfig getFromConfig() { + return fromConfig; } - public void setVersion(String version) { - this.version = version; + public MToConfig getToConfig() { + return toConfig; + } + + public String getVersion() { + return version; } public SupportedDirections getSupportedDirections() { - return new SupportedDirections(this.getJobForms(Direction.FROM) != null, - this.getJobForms(Direction.TO) != null); + return new SupportedDirections(this.getConfig(Direction.FROM) != null, + this.getConfig(Direction.TO) != null); } }
http://git-wip-us.apache.org/repos/asf/sqoop/blob/8362c73c/common/src/main/java/org/apache/sqoop/model/MDriver.java ---------------------------------------------------------------------- diff --git a/common/src/main/java/org/apache/sqoop/model/MDriver.java b/common/src/main/java/org/apache/sqoop/model/MDriver.java new file mode 100644 index 0000000..685439e --- /dev/null +++ b/common/src/main/java/org/apache/sqoop/model/MDriver.java @@ -0,0 +1,82 @@ +/** + * 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.sql.Driver; + +/** + * Describes the configs associated with the {@link Driver} for executing sqoop jobs. + */ +public class MDriver extends MPersistableEntity implements MClonable { + + private final MDriverConfig driverConfig; + private final String version; + + public MDriver(MDriverConfig driverConfig, String version) { + this.driverConfig = driverConfig; + this.version = version; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("driver-"); + sb.append(getPersistenceId()).append(":"); + sb.append("version = " + version); + sb.append(", ").append(driverConfig.toString()); + + return sb.toString(); + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + + if (!(other instanceof MDriver)) { + return false; + } + + MDriver driver = (MDriver) other; + return version.equals(driver.getVersion()) && + driverConfig.equals(driver.driverConfig); + } + + @Override + public int hashCode() { + int result = driverConfig.hashCode(); + result = 31 * result + version.hashCode(); + return result; + } + + public MDriverConfig getDriverConfig() { + return driverConfig; + } + + @Override + public MDriver clone(boolean cloneWithValue) { + cloneWithValue = false; + MDriver copy = new MDriver(this.driverConfig.clone(cloneWithValue), this.version); + copy.setPersistenceId(this.getPersistenceId()); + return copy; + } + + public String getVersion() { + return version; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/sqoop/blob/8362c73c/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 62eb197..679859a 100644 --- a/common/src/main/java/org/apache/sqoop/model/MDriverConfig.java +++ b/common/src/main/java/org/apache/sqoop/model/MDriverConfig.java @@ -17,29 +17,23 @@ */ package org.apache.sqoop.model; -/** - * Describes the configs associated with the {@link Driver} for executing sqoop jobs. - */ -public class MDriverConfig extends MPersistableEntity implements MClonable { +import java.util.List; - private final MConnectionForms connectionForms; - private final MJobForms jobForms; - String version; +/** + * Config describing all required information for the driver + * NOTE: It extends a config list since {@link MToConfig} could consist of a related config groups + * In future this could be simplified to hold a single list of all configs for the driver - public MDriverConfig(MConnectionForms connectionForms, MJobForms jobForms, String version) { - this.connectionForms = connectionForms; - this.jobForms = jobForms; - this.version = version; + */ +public class MDriverConfig extends MConfigList { + public MDriverConfig(List<MConfig> configs) { + super(configs); } @Override public String toString() { - StringBuilder sb = new StringBuilder("driver-"); - sb.append(getPersistenceId()).append(":"); - sb.append("version = " + version); - sb.append(", ").append(connectionForms.toString()); - sb.append(jobForms.toString()); - + StringBuilder sb = new StringBuilder("Driver:"); + sb.append(super.toString()); return sb.toString(); } @@ -53,45 +47,18 @@ public class MDriverConfig extends MPersistableEntity implements MClonable { return false; } - MDriverConfig mo = (MDriverConfig) other; - return version.equals(mo.getVersion()) && - connectionForms.equals(mo.connectionForms) && - jobForms.equals(mo.jobForms); + MDriverConfig mDriver = (MDriverConfig) other; + return super.equals(mDriver); } @Override public int hashCode() { - int result = connectionForms.hashCode(); - result = 31 * result + jobForms.hashCode(); - result = 31 * result + version.hashCode(); - return result; - } - - public MConnectionForms getConnectionForms() { - return connectionForms; - } - - public MJobForms getJobForms() { - return jobForms; + return super.hashCode(); } @Override public MDriverConfig clone(boolean cloneWithValue) { - //Framework never have any values filled - cloneWithValue = false; - MDriverConfig copy = new MDriverConfig(this.getConnectionForms().clone(cloneWithValue), - this.getJobForms().clone(cloneWithValue), this.version); - copy.setPersistenceId(this.getPersistenceId()); + MDriverConfig copy = new MDriverConfig(super.clone(cloneWithValue).getConfigs()); return copy; } - - public String getVersion() { - return version; - } - - public void setVersion(String version) { - this.version = version; - } - -} - +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/sqoop/blob/8362c73c/common/src/main/java/org/apache/sqoop/model/MForm.java ---------------------------------------------------------------------- diff --git a/common/src/main/java/org/apache/sqoop/model/MForm.java b/common/src/main/java/org/apache/sqoop/model/MForm.java deleted file mode 100644 index ff94660..0000000 --- a/common/src/main/java/org/apache/sqoop/model/MForm.java +++ /dev/null @@ -1,117 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.sqoop.model; - -import org.apache.sqoop.common.SqoopException; - -import java.util.ArrayList; -import java.util.List; - -/** - * Represents a group of inputs that are processed together. This allows the - * input gathering process to be broken down into multiple steps that can be - * then paged through by the user interface. - */ -public final class MForm extends MValidatedElement implements MClonable { - - private final List<MInput<?>> inputs; - - public MForm(String name, List<MInput<?>> inputs) { - super(name); - - this.inputs = inputs; - } - - public List<MInput<?>> getInputs() { - return inputs; - } - - public MInput<?> getInput(String inputName) { - for(MInput<?> input: inputs) { - if(inputName.equals(input.getName())) { - return input; - } - } - - throw new SqoopException(ModelError.MODEL_011, "Input name: " + inputName); - } - - public MStringInput getStringInput(String inputName) { - return (MStringInput)getInput(inputName); - } - - public MEnumInput getEnumInput(String inputName) { - return (MEnumInput)getInput(inputName); - } - - public MIntegerInput getIntegerInput(String inputName) { - return (MIntegerInput)getInput(inputName); - } - - public MBooleanInput getBooleanInput(String inputName) { - return (MBooleanInput)getInput(inputName); - } - - public MMapInput getMapInput(String inputName) { - return (MMapInput)getInput(inputName); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder("form-").append(getName()); - sb.append(":").append(getPersistenceId()).append(":").append(inputs); - - return sb.toString(); - } - - @Override - public boolean equals(Object other) { - if (other == this) { - return true; - } - - if (!(other instanceof MForm)) { - return false; - } - - MForm mf = (MForm) other; - return getName().equals(mf.getName()) - && inputs.equals(mf.inputs); - } - - @Override - public int hashCode() { - int result = 17; - result = 31 * result + getName().hashCode(); - for (MInput<?> mi : inputs) { - result = 31 * result + mi.hashCode(); - } - - return result; - } - - @Override - public MForm clone(boolean cloneWithValue) { - List<MInput<?>> copyInputs = new ArrayList<MInput<?>>(); - for(MInput<?> itr : this.getInputs()) { - copyInputs.add((MInput<?>)itr.clone(cloneWithValue)); - } - MForm copyForm = new MForm(this.getName(), copyInputs); - return copyForm; - } -} http://git-wip-us.apache.org/repos/asf/sqoop/blob/8362c73c/common/src/main/java/org/apache/sqoop/model/MFormList.java ---------------------------------------------------------------------- diff --git a/common/src/main/java/org/apache/sqoop/model/MFormList.java b/common/src/main/java/org/apache/sqoop/model/MFormList.java deleted file mode 100644 index 9130ada..0000000 --- a/common/src/main/java/org/apache/sqoop/model/MFormList.java +++ /dev/null @@ -1,124 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.sqoop.model; - -import org.apache.sqoop.common.SqoopException; - -import java.util.ArrayList; -import java.util.List; - -/** - * Arbitrary list of forms. - */ -public class MFormList implements MClonable { - - private final List<MForm> forms; - - public MFormList(List<MForm> forms) { - this.forms = forms; - } - - public List<MForm> getForms() { - return forms; - } - - public MForm getForm(String formName) { - for(MForm form: forms) { - if(formName.equals(form.getName())) { - return form; - } - } - - throw new SqoopException(ModelError.MODEL_010, "Form name: " + formName); - } - - public MInput getInput(String name) { - String []parts = name.split("\\."); - if(parts.length != 2) { - throw new SqoopException(ModelError.MODEL_009, name); - } - - return getForm(parts[0]).getInput(name); - } - - public MStringInput getStringInput(String name) { - return (MStringInput)getInput(name); - } - - public MEnumInput getEnumInput(String name) { - return (MEnumInput)getInput(name); - } - - public MIntegerInput getIntegerInput(String name) { - return (MIntegerInput)getInput(name); - } - - public MMapInput getMapInput(String name) { - return (MMapInput)getInput(name); - } - - public MBooleanInput getBooleanInput(String name) { - return (MBooleanInput)getInput(name); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof MFormList)) return false; - - MFormList mFormList = (MFormList) o; - - if (!forms.equals(mFormList.forms)) return false; - - return true; - } - - @Override - public int hashCode() { - int result = super.hashCode(); - for(MForm form : forms) { - result = 31 * result + form.hashCode(); - } - - return result; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder("Forms: "); - for(MForm form : forms) { - sb.append(form.toString()); - } - return sb.toString(); - } - - @Override - public MFormList clone(boolean cloneWithValue) { - List<MForm> copyForms = null; - if(this.getForms() != null) { - copyForms = new ArrayList<MForm>(); - for(MForm itr : this.getForms()) { - MForm newForm = itr.clone(cloneWithValue); - newForm.setPersistenceId(itr.getPersistenceId()); - copyForms.add(newForm); - } - } - MFormList copyFormList = new MFormList(copyForms); - return copyFormList; - } -} http://git-wip-us.apache.org/repos/asf/sqoop/blob/8362c73c/common/src/main/java/org/apache/sqoop/model/MFormType.java ---------------------------------------------------------------------- diff --git a/common/src/main/java/org/apache/sqoop/model/MFormType.java b/common/src/main/java/org/apache/sqoop/model/MFormType.java deleted file mode 100644 index 2f403df..0000000 --- a/common/src/main/java/org/apache/sqoop/model/MFormType.java +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.sqoop.model; - -/** - * Represents the various form types supported by the system. - */ -public enum MFormType { - - /** Unknown form type */ - OTHER, - - /** Connection form type */ - CONNECTION, - - /** Job form type */ - JOB; - -} http://git-wip-us.apache.org/repos/asf/sqoop/blob/8362c73c/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 new file mode 100644 index 0000000..1b450d6 --- /dev/null +++ b/common/src/main/java/org/apache/sqoop/model/MFromConfig.java @@ -0,0 +1,64 @@ +/** + * 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.util.List; + +/** + * Config describing all required information to build the FROM part of the job + * NOTE: It extends a config list since {@link MFromConfig} could consist of a related config groups + * In future this could be simplified to hold a single list of all configs for the FROM object + + */ +public class MFromConfig extends MConfigList { + public MFromConfig(List<MConfig> configs) { + super(configs); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("From: "); + sb.append(super.toString()); + return sb.toString(); + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + + if (!(other instanceof MFromConfig)) { + return false; + } + + MFromConfig mj = (MFromConfig) other; + return super.equals(mj); + } + + @Override + public int hashCode() { + return super.hashCode(); + } + + @Override + public MFromConfig clone(boolean cloneWithValue) { + MFromConfig copy = new MFromConfig(super.clone(cloneWithValue).getConfigs()); + return copy; + } +} http://git-wip-us.apache.org/repos/asf/sqoop/blob/8362c73c/common/src/main/java/org/apache/sqoop/model/MJob.java ---------------------------------------------------------------------- diff --git a/common/src/main/java/org/apache/sqoop/model/MJob.java b/common/src/main/java/org/apache/sqoop/model/MJob.java index c9b45a5..b3dec27 100644 --- a/common/src/main/java/org/apache/sqoop/model/MJob.java +++ b/common/src/main/java/org/apache/sqoop/model/MJob.java @@ -22,29 +22,23 @@ import org.apache.sqoop.common.DirectionError; import org.apache.sqoop.common.SqoopException; /** - * Model describing entire job object including both connector and - * framework part. + * Model describing entire job object including the from/to and driver config information + * to execute the job */ public class MJob extends MAccountableEntity implements MClonable { /** - * Connector reference. - * - * Job object do not immediately depend on connector as there is indirect + * NOTE : Job object do not immediately depend on connector as there is indirect * dependency through link object, but having this dependency explicitly - * carried along helps a lot. + * carried along helps with not having to make the DB call everytime */ private final long fromConnectorId; private final long toConnectorId; - - /** - * Corresponding link objects for connector. - */ private final long fromLinkId; private final long toLinkId; - private final MJobForms fromConnectorPart; - private final MJobForms toConnectorPart; - private final MJobForms frameworkPart; + private final MFromConfig fromConfig; + private final MToConfig toConfig; + private final MDriverConfig driverConfig; /** * Default constructor to build new MJob model. @@ -53,24 +47,24 @@ public class MJob extends MAccountableEntity implements MClonable { * @param toConnectorId TO Connector id * @param fromLinkId FROM Link id * @param toLinkId TO Link id - * @param fromPart FROM Connector forms - * @param toPart TO Connector forms - * @param frameworkPart Framework forms + * @param fromConfig FROM job config + * @param toConfig TO job config + * @param driverConfig driver config */ public MJob(long fromConnectorId, long toConnectorId, - long fromConnectionId, - long toConnectionId, - MJobForms fromPart, - MJobForms toPart, - MJobForms frameworkPart) { + long fromLinkId, + long toLinkId, + MFromConfig fromConfig, + MToConfig toConfig, + MDriverConfig driverConfig) { this.fromConnectorId = fromConnectorId; this.toConnectorId = toConnectorId; - this.fromLinkId = fromConnectionId; - this.toLinkId = toConnectionId; - this.fromConnectorPart = fromPart; - this.toConnectorPart = toPart; - this.frameworkPart = frameworkPart; + this.fromLinkId = fromLinkId; + this.toLinkId = toLinkId; + this.fromConfig = fromConfig; + this.toConfig = toConfig; + this.driverConfig = driverConfig; } /** @@ -80,9 +74,9 @@ public class MJob extends MAccountableEntity implements MClonable { */ public MJob(MJob other) { this(other, - other.getConnectorPart(Direction.FROM).clone(true), - other.getConnectorPart(Direction.TO).clone(true), - other.frameworkPart.clone(true)); + other.getFromJobConfig().clone(true), + other.getToJobConfig().clone(true), + other.driverConfig.clone(true)); } /** @@ -92,29 +86,29 @@ public class MJob extends MAccountableEntity implements MClonable { * used otherwise. * * @param other MJob model to copy - * @param fromPart FROM Connector forms - * @param toPart TO Connector forms - * @param frameworkPart Framework forms + * @param fromConfig FROM Job config + * @param toConfig TO Job config + * @param driverConfig driverConfig */ - public MJob(MJob other, MJobForms fromPart, MJobForms toPart, MJobForms frameworkPart) { + public MJob(MJob other, MFromConfig fromConfig, MToConfig toConfig, MDriverConfig driverConfig) { super(other); this.fromConnectorId = other.getConnectorId(Direction.FROM); this.toConnectorId = other.getConnectorId(Direction.TO); this.fromLinkId = other.getLinkId(Direction.FROM); this.toLinkId = other.getLinkId(Direction.TO); - this.fromConnectorPart = fromPart; - this.toConnectorPart = toPart; - this.frameworkPart = frameworkPart; + this.fromConfig = fromConfig; + this.toConfig = toConfig; + this.driverConfig = driverConfig; this.setPersistenceId(other.getPersistenceId()); } @Override public String toString() { StringBuilder sb = new StringBuilder("job"); - sb.append(" connector-from-part: ").append(getConnectorPart(Direction.FROM)); - sb.append(", connector-to-part: ").append(getConnectorPart(Direction.TO)); - sb.append(", framework-part: ").append(frameworkPart); + sb.append("From job config: ").append(getJobConfig(Direction.FROM)); + sb.append(", To job config: ").append(getJobConfig(Direction.TO)); + sb.append(", Driver config: ").append(driverConfig); return sb.toString(); } @@ -145,21 +139,29 @@ public class MJob extends MAccountableEntity implements MClonable { } } - public MJobForms getConnectorPart(Direction type) { + public MConfigList getJobConfig(Direction type) { switch(type) { case FROM: - return fromConnectorPart; + return fromConfig; case TO: - return toConnectorPart; + return toConfig; default: throw new SqoopException(DirectionError.DIRECTION_0000, "Direction: " + type); } } - public MJobForms getFrameworkPart() { - return frameworkPart; + public MFromConfig getFromJobConfig() { + return fromConfig; + } + + public MToConfig getToJobConfig() { + return toConfig; + } + + public MDriverConfig getDriverConfig() { + return driverConfig; } @Override @@ -172,9 +174,9 @@ public class MJob extends MAccountableEntity implements MClonable { getConnectorId(Direction.TO), getLinkId(Direction.FROM), getLinkId(Direction.TO), - getConnectorPart(Direction.FROM).clone(false), - getConnectorPart(Direction.TO).clone(false), - frameworkPart.clone(false)); + getFromJobConfig().clone(false), + getToJobConfig().clone(false), + getDriverConfig().clone(false)); } } @@ -194,8 +196,8 @@ public class MJob extends MAccountableEntity implements MClonable { && (job.getLinkId(Direction.FROM) == this.getLinkId(Direction.FROM)) && (job.getLinkId(Direction.TO) == this.getLinkId(Direction.TO)) && (job.getPersistenceId() == this.getPersistenceId()) - && (job.getConnectorPart(Direction.FROM).equals(this.getConnectorPart(Direction.FROM))) - && (job.getConnectorPart(Direction.TO).equals(this.getConnectorPart(Direction.TO))) - && (job.frameworkPart.equals(this.frameworkPart)); + && (job.getFromJobConfig().equals(this.getJobConfig(Direction.FROM))) + && (job.getToJobConfig().equals(this.getJobConfig(Direction.TO))) + && (job.getDriverConfig().equals(this.driverConfig)); } } http://git-wip-us.apache.org/repos/asf/sqoop/blob/8362c73c/common/src/main/java/org/apache/sqoop/model/MJobForms.java ---------------------------------------------------------------------- diff --git a/common/src/main/java/org/apache/sqoop/model/MJobForms.java b/common/src/main/java/org/apache/sqoop/model/MJobForms.java deleted file mode 100644 index 08b9a78..0000000 --- a/common/src/main/java/org/apache/sqoop/model/MJobForms.java +++ /dev/null @@ -1,55 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.sqoop.model; - -import java.util.List; - -/** - * Metadata describing all required information to build a job - * object with two connectors and a framework. - */ -public class MJobForms extends MFormList { - public MJobForms(List<MForm> forms) { - super(forms); - } - - @Override - public boolean equals(Object other) { - if (other == this) { - return true; - } - - if (!(other instanceof MJobForms)) { - return false; - } - - MJobForms mj = (MJobForms) other; - return super.equals(mj); - } - - @Override - public int hashCode() { - return super.hashCode(); - } - - @Override - public MJobForms clone(boolean cloneWithValue) { - MJobForms copy = new MJobForms(super.clone(cloneWithValue).getForms()); - return copy; - } -} http://git-wip-us.apache.org/repos/asf/sqoop/blob/8362c73c/common/src/main/java/org/apache/sqoop/model/MLink.java ---------------------------------------------------------------------- diff --git a/common/src/main/java/org/apache/sqoop/model/MLink.java b/common/src/main/java/org/apache/sqoop/model/MLink.java index 6a8c424..7a9f538 100644 --- a/common/src/main/java/org/apache/sqoop/model/MLink.java +++ b/common/src/main/java/org/apache/sqoop/model/MLink.java @@ -22,57 +22,49 @@ package org.apache.sqoop.model; */ public class MLink extends MAccountableEntity implements MClonable { private long connectorId; - - private final MConnectionForms connectorPart; - private final MConnectionForms frameworkPart; + // NOTE: we hold this in the model for easy access to the link config object, it might as well be retrieved on the fly using the connectorId + private final MLinkConfig connectorLinkConfig; /** - * Default constructor to build new MConnection model. + * Default constructor to build new MLink model. * * @param connectorId Connector id - * @param connectorPart Connector forms - * @param frameworkPart Framework forms + * @param linkConfig Connector forms */ - public MLink(long connectorId, - MConnectionForms connectorPart, - MConnectionForms frameworkPart) { + public MLink(long connectorId, MLinkConfig linkConfig) { this.connectorId = connectorId; - this.connectorPart = connectorPart; - this.frameworkPart = frameworkPart; + this.connectorLinkConfig = linkConfig; } /** - * Constructor to create deep copy of another MConnection model. + * Constructor to create deep copy of another MLink model. * - * @param other MConnection model to copy + * @param other MLink model to copy */ public MLink(MLink other) { - this(other, other.connectorPart.clone(true), other.frameworkPart.clone(true)); + this(other, other.connectorLinkConfig.clone(true)); } /** - * Construct new MConnection model as a copy of another with replaced forms. + * Construct new MLink model as a copy of another with replaced forms. * - * This method is suitable only for metadata upgrade path and should not be + * This method is suitable only for link upgrade path and should not be * used otherwise. * - * @param other MConnection model to copy - * @param connectorPart Connector forms - * @param frameworkPart Framework forms + * @param other MLink model to copy + * @param linkConfig link config */ - public MLink(MLink other, MConnectionForms connectorPart, MConnectionForms frameworkPart) { + public MLink(MLink other, MLinkConfig linkConfig) { super(other); this.connectorId = other.connectorId; - this.connectorPart = connectorPart; - this.frameworkPart = frameworkPart; + this.connectorLinkConfig = linkConfig; this.setPersistenceId(other.getPersistenceId()); } @Override public String toString() { - StringBuilder sb = new StringBuilder("connection: ").append(getName()); - sb.append(" connector-part: ").append(connectorPart); - sb.append(", framework-part: ").append(frameworkPart); + StringBuilder sb = new StringBuilder("link: ").append(getName()); + sb.append(" link-config: ").append(connectorLinkConfig); return sb.toString(); } @@ -85,20 +77,11 @@ public class MLink extends MAccountableEntity implements MClonable { this.connectorId = connectorId; } - public MConnectionForms getConnectorPart() { - return connectorPart; - } - - public MConnectionForms getFrameworkPart() { - return frameworkPart; - } - - public MForm getConnectorForm(String formName) { - return connectorPart.getForm(formName); + public MLinkConfig getConnectorLinkConfig() { + return connectorLinkConfig; } - - public MForm getFrameworkForm(String formName) { - return frameworkPart.getForm(formName); + public MConfig getConnectorLinkConfig(String formName) { + return connectorLinkConfig.getConfig(formName); } @Override @@ -106,7 +89,7 @@ public class MLink extends MAccountableEntity implements MClonable { if(cloneWithValue) { return new MLink(this); } else { - return new MLink(connectorId, connectorPart.clone(false), frameworkPart.clone(false)); + return new MLink(connectorId, connectorLinkConfig.clone(false)); } } @@ -120,10 +103,9 @@ public class MLink extends MAccountableEntity implements MClonable { return false; } - MLink mc = (MLink)object; - return (mc.connectorId == this.connectorId) - && (mc.getPersistenceId() == this.getPersistenceId()) - && (mc.connectorPart.equals(this.connectorPart)) - && (mc.frameworkPart.equals(this.frameworkPart)); - } + MLink mLink = (MLink)object; + return (mLink.connectorId == this.connectorId) + && (mLink.getPersistenceId() == this.getPersistenceId()) + && (mLink.connectorLinkConfig.equals(this.connectorLinkConfig)); + } } http://git-wip-us.apache.org/repos/asf/sqoop/blob/8362c73c/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 new file mode 100644 index 0000000..318b63c --- /dev/null +++ b/common/src/main/java/org/apache/sqoop/model/MLinkConfig.java @@ -0,0 +1,54 @@ +/** + * 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.util.List; + +/** + * Config describing all required information to build up an link object + * NOTE: It extends a config list since {@link MLink} could consist of a related config groups + * In future this could be simplified to hold a single list of all configs for the link object + */ +public class MLinkConfig extends MConfigList { + + public MLinkConfig(List<MConfig> configs) { + super(configs); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("Link: "); + sb.append(super.toString()); + return sb.toString(); + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + + return super.equals(other); + } + + @Override + public MLinkConfig clone(boolean cloneWithValue) { + MLinkConfig copy = new MLinkConfig(super.clone(cloneWithValue).getConfigs()); + return copy; + } +} http://git-wip-us.apache.org/repos/asf/sqoop/blob/8362c73c/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 new file mode 100644 index 0000000..b4fbe41 --- /dev/null +++ b/common/src/main/java/org/apache/sqoop/model/MToConfig.java @@ -0,0 +1,64 @@ +/** + * 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.util.List; + +/** + * Config describing all required information to build the TO part of the job + * NOTE: It extends a config list since {@link MToConfig} could consist of a related config groups + * In future this could be simplified to hold a single list of all configs for the TO object + + */ +public class MToConfig extends MConfigList { + public MToConfig(List<MConfig> configs) { + super(configs); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("To: "); + sb.append(super.toString()); + return sb.toString(); + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + + if (!(other instanceof MToConfig)) { + return false; + } + + MToConfig mj = (MToConfig) other; + return super.equals(mj); + } + + @Override + public int hashCode() { + return super.hashCode(); + } + + @Override + public MToConfig clone(boolean cloneWithValue) { + MToConfig copy = new MToConfig(super.clone(cloneWithValue).getConfigs()); + return copy; + } +} http://git-wip-us.apache.org/repos/asf/sqoop/blob/8362c73c/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 74e924e..35a8943 100644 --- a/common/src/main/java/org/apache/sqoop/model/ModelError.java +++ b/common/src/main/java/org/apache/sqoop/model/ModelError.java @@ -24,7 +24,7 @@ import org.apache.sqoop.common.ErrorCode; */ public enum ModelError implements ErrorCode { - MODEL_001("Attempt to pass two different set of MForms for single job type."), + MODEL_001("Attempt to pass two different set of MConfigs for single job type."), MODEL_002("Creating MJob of different job types"), @@ -34,7 +34,7 @@ public enum ModelError implements ErrorCode { MODEL_005("Can't get field value"), - MODEL_006("Incompatible form list and configuration object"), + MODEL_006("Incompatible config list and configuration object"), MODEL_007("Primitive types in configuration objects are not allowed"), @@ -42,7 +42,7 @@ public enum ModelError implements ErrorCode { MODEL_009("Invalid input name"), - MODEL_010("Form do not exist"), + MODEL_010("Config do not exist"), MODEL_011("Input do not exist"), http://git-wip-us.apache.org/repos/asf/sqoop/blob/8362c73c/common/src/main/java/org/apache/sqoop/utils/ClassUtils.java ---------------------------------------------------------------------- diff --git a/common/src/main/java/org/apache/sqoop/utils/ClassUtils.java b/common/src/main/java/org/apache/sqoop/utils/ClassUtils.java index eca9f7e..0be4d41 100644 --- a/common/src/main/java/org/apache/sqoop/utils/ClassUtils.java +++ b/common/src/main/java/org/apache/sqoop/utils/ClassUtils.java @@ -17,14 +17,12 @@ */ package org.apache.sqoop.utils; -import org.apache.log4j.Logger; - import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; + +import org.apache.log4j.Logger; public final class ClassUtils { http://git-wip-us.apache.org/repos/asf/sqoop/blob/8362c73c/common/src/main/java/org/apache/sqoop/validation/ConfigValidationError.java ---------------------------------------------------------------------- diff --git a/common/src/main/java/org/apache/sqoop/validation/ConfigValidationError.java b/common/src/main/java/org/apache/sqoop/validation/ConfigValidationError.java new file mode 100644 index 0000000..3453648 --- /dev/null +++ b/common/src/main/java/org/apache/sqoop/validation/ConfigValidationError.java @@ -0,0 +1,52 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.sqoop.validation; + +import org.apache.sqoop.common.ErrorCode; + +/** + * + */ +public enum ConfigValidationError implements ErrorCode { + + VALIDATION_0000("Unknown error"), + + VALIDATION_0001("Missing class declaration."), + + VALIDATION_0002("Usage of missing field"), + + VALIDATION_0003("Invalid representation of config and input field"), + + VALIDATION_0004("Can't find validator class"), + + ; + + private final String message; + + private ConfigValidationError(String message) { + this.message = message; + } + + public String getCode() { + return name(); + } + + public String getMessage() { + return message; + } +} http://git-wip-us.apache.org/repos/asf/sqoop/blob/8362c73c/common/src/main/java/org/apache/sqoop/validation/ConfigValidationResult.java ---------------------------------------------------------------------- diff --git a/common/src/main/java/org/apache/sqoop/validation/ConfigValidationResult.java b/common/src/main/java/org/apache/sqoop/validation/ConfigValidationResult.java new file mode 100644 index 0000000..4c4d123 --- /dev/null +++ b/common/src/main/java/org/apache/sqoop/validation/ConfigValidationResult.java @@ -0,0 +1,98 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.sqoop.validation; + +import org.apache.sqoop.validation.validators.AbstractValidator; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Result of validation execution. + */ +public class ConfigValidationResult { + + /** + * All messages for each named item. + */ + Map<String, List<Message>> messages; + + /** + * Overall status. + */ + Status status; + + public ConfigValidationResult() { + messages = new HashMap<String, List<Message>>(); + status = Status.getDefault(); + } + + /** + * Add given validator result to this instance. + * + * @param name Full name of the validated object + * @param validator Executed validator + */ + public void addValidatorResult(String name, AbstractValidator<String> validator) { + if(validator.getStatus() == Status.getDefault()) { + return; + } + + status = Status.getWorstStatus(status, validator.getStatus()); + if(messages.containsKey(name)) { + messages.get(name).addAll(validator.getMessages()); + } else { + messages.put(name, validator.getMessages()); + } + } + + /** + * Merge results with another validation result. + * + * @param result Other validation result + */ + public void mergeValidatorResult(ConfigValidationResult result) { + messages.putAll(result.messages); + status = Status.getWorstStatus(status, result.status); + } + + /** + * Method to directly add messages for given name. + * + * This method will replace previous messages for given name. + * + * @param name Name of the entity + * @param messages List of messages associated with the name + */ + public void addMessages(String name, List<Message> messages) { + this.messages.put(name, messages); + + for(Message message : messages) { + this.status = Status.getWorstStatus(status, message.getStatus()); + } + } + + public Status getStatus() { + return status; + } + + public Map<String, List<Message>> getMessages() { + return messages; + } +} http://git-wip-us.apache.org/repos/asf/sqoop/blob/8362c73c/common/src/main/java/org/apache/sqoop/validation/ConfigValidationRunner.java ---------------------------------------------------------------------- diff --git a/common/src/main/java/org/apache/sqoop/validation/ConfigValidationRunner.java b/common/src/main/java/org/apache/sqoop/validation/ConfigValidationRunner.java new file mode 100644 index 0000000..8c66b3d --- /dev/null +++ b/common/src/main/java/org/apache/sqoop/validation/ConfigValidationRunner.java @@ -0,0 +1,177 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.sqoop.validation; + +import org.apache.sqoop.common.SqoopException; +import org.apache.sqoop.model.ConfigurationClass; +import org.apache.sqoop.model.Config; +import org.apache.sqoop.model.ConfigClass; +import org.apache.sqoop.model.ConfigUtils; +import org.apache.sqoop.model.Input; +import org.apache.sqoop.model.Validator; +import org.apache.sqoop.utils.ClassUtils; +import org.apache.sqoop.validation.validators.AbstractValidator; + +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; + +/** + * Validation runner that will run validators associated with given configuration + * class or config object. + * + * Execution follows following rules: + * * Run children first (Inputs -> Config -> Class) + * * If any children is not suitable (canProceed = false), skip running parent + * + * Which means that config validator don't have to repeat it's input validators as it will + * be never called if the input's are not valid. Similarly Class validators won't be called + * unless all configs will pass validators. + * + */ +public class ConfigValidationRunner { + + /** + * Private cache of instantiated validators. + * + * We're expecting that this cache will be very small as the number of possible validators + * is driven to high extent by the number of connectors and hence we don't have a cache + * eviction at the moment. + */ + private Map<Class<? extends AbstractValidator>, AbstractValidator> cache; + + public ConfigValidationRunner() { + cache = new HashMap<Class<? extends AbstractValidator>, AbstractValidator>(); + } + + /** + * Validate given configuration instance. + * + * @param config Configuration instance + * @return + */ + public ConfigValidationResult validate(Object config) { + ConfigValidationResult result = new ConfigValidationResult(); + ConfigurationClass globalAnnotation = ConfigUtils.getConfigurationClassAnnotation(config, true); + + // Iterate over all declared config and call their validators + for (Field field : config.getClass().getDeclaredFields()) { + field.setAccessible(true); + + Config configAnnotation = ConfigUtils.getConfigAnnotation(field, false); + if(configAnnotation == null) { + continue; + } + + String configName = ConfigUtils.getName(field, configAnnotation); + ConfigValidationResult r = validateConfig(configName, ConfigUtils.getFieldValue(field, config)); + result.mergeValidatorResult(r); + } + + // Call class validator only as long as we are in suitable state + if(result.getStatus().canProceed()) { + ConfigValidationResult r = validateArray("", config, globalAnnotation.validators()); + result.mergeValidatorResult(r); + } + + return result; + } + + /** + * Validate given config instance. + * + * @param configName Config's name to build full name for all inputs. + * @param config Config instance + * @return + */ + public ConfigValidationResult validateConfig(String configName, Object config) { + ConfigValidationResult result = new ConfigValidationResult(); + ConfigClass configAnnotation = ConfigUtils.getConfigClassAnnotation(config, true); + + // Iterate over all declared inputs and call their validators + for (Field field : config.getClass().getDeclaredFields()) { + Input inputAnnotation = ConfigUtils.getInputAnnotation(field, false); + if(inputAnnotation == null) { + continue; + } + + String name = configName + "." + ConfigUtils.getName(field, inputAnnotation); + + ConfigValidationResult r = validateArray(name, ConfigUtils.getFieldValue(field, config), inputAnnotation.validators()); + result.mergeValidatorResult(r); + } + + // Call config validator only as long as we are in suitable state + if(result.getStatus().canProceed()) { + ConfigValidationResult r = validateArray(configName, config, configAnnotation.validators()); + result.mergeValidatorResult(r); + } + + return result; + } + + /** + * Execute array of validators on given object (can be input/config/class). + * + * @param name Full name of the object + * @param object Input, Config or Class instance + * @param validators Validators array + * @return + */ + private ConfigValidationResult validateArray(String name, Object object, Validator[] validators) { + ConfigValidationResult result = new ConfigValidationResult(); + + for (Validator validator : validators) { + AbstractValidator v = executeValidator(object, validator); + result.addValidatorResult(name, v); + } + + return result; + } + + /** + * Execute single validator. + * + * @param object Input, Config or Class instance + * @param validator Validator annotation + * @return + */ + private AbstractValidator executeValidator(Object object, Validator validator) { + // Try to get validator instance from the cache + AbstractValidator instance = cache.get(validator.value()); + + if(instance == null) { + instance = (AbstractValidator) ClassUtils.instantiate(validator.value()); + + // This could happen if we would be missing some connector's jars on our classpath + if(instance == null) { + throw new SqoopException(ConfigValidationError.VALIDATION_0004, validator.value().getName()); + } + + cache.put(validator.value(), instance); + } else { + instance.reset(); + } + + instance.setStringArgument(validator.strArg()); + instance.validate(object); + return instance; + } + + +} http://git-wip-us.apache.org/repos/asf/sqoop/blob/8362c73c/common/src/main/java/org/apache/sqoop/validation/ConfigValidator.java ---------------------------------------------------------------------- diff --git a/common/src/main/java/org/apache/sqoop/validation/ConfigValidator.java b/common/src/main/java/org/apache/sqoop/validation/ConfigValidator.java new file mode 100644 index 0000000..eac789e --- /dev/null +++ b/common/src/main/java/org/apache/sqoop/validation/ConfigValidator.java @@ -0,0 +1,228 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.sqoop.validation; + +import org.apache.sqoop.common.SqoopException; + +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; + +/** + * Config validators. + * + * This class represents validations for the sqoop objects + */ +public class ConfigValidator { + + // Configuration class that belongs to this validation + Class klass; + + // Entire validation status + Status status; + + // Status messages for various fields + Map<ConfigInput, Message> messages; + + public ConfigValidator(Class klass) { + this.klass = klass; + status = Status.getDefault(); + messages = new HashMap<ConfigInput, Message>(); + } + + public ConfigValidator(Status status, Map<ConfigInput, Message> messages) { + this.status = status; + this.messages = messages; + } + + public Status getStatus() { + return status; + } + + public Map<ConfigInput, Message> getMessages() { + return messages; + } + + /** + * Add message to config. + * + * @param status Severity of the message + * @param config Config name, must be defined in the class + * @param message Validation message + */ + public void addMessage(Status status, String config, String message) { + addMessage(status, config, null, message); + } + + /** + * Add message to input in one of the configs. + * + * @param status Severity of the message + * @param config Config name, must be defined in the class + * @param input Field name, must be defined in the config class + * @param message Validation message + */ + public void addMessage(Status status, String config, String input, String message ) { + if( klass == null) { + throw new SqoopException(ConfigValidationError.VALIDATION_0001); + } + + assert config != null; + assert message != null; + + // Field for specified config + Field configField; + + // Load the config field and verify that it exists + try { + configField = klass.getDeclaredField(config); + } catch (NoSuchFieldException e) { + throw new SqoopException(ConfigValidationError.VALIDATION_0002, + "Can't get config " + config + " from " + klass.getName(), e); + } + + // If this is config message, just save the message and continue + if(input == null) { + setMessage(status, config, input, message); + return; + } + + // Verify that specified input exists on the config + try { + configField.getType().getDeclaredField(input); + } catch (NoSuchFieldException e) { + throw new SqoopException(ConfigValidationError.VALIDATION_0002, + "Can't get input " + input + " from config" + configField.getType().getName(), e); + } + + setMessage(status, config, input, message); + } + + private void setMessage(Status status, String config, String input, String message) { + this.status = Status.getWorstStatus(this.status, status); + messages.put(new ConfigInput(config, input), new Message(status, message)); + } + + public static class Message { + private Status status; + private String message; + + public Message(Status status, String message) { + this.status = status; + this.message = message; + } + + public Status getStatus() { + return status; + } + + public String getMessage() { + return message; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof Message)) return false; + + Message message1 = (Message) o; + + if (message != null ? !message.equals(message1.message) : message1.message != null) + return false; + if (status != message1.status) return false; + + return true; + } + + @Override + public int hashCode() { + int result = status != null ? status.hashCode() : 0; + result = 31 * result + (message != null ? message.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return "{" + status.name() + ": " + message + "}"; + } + } + + public static class ConfigInput{ + private String config; + private String input; + + public ConfigInput(String config, String input) { + this.config = config; + this.input = input; + } + + public ConfigInput(String configInput) { + assert configInput != null; + String []parts = configInput.split("\\."); + + if(configInput.isEmpty() || (parts.length != 1 && parts.length != 2)) { + throw new SqoopException(ConfigValidationError.VALIDATION_0003, + "Specification " + configInput + " is not in valid configat config.input"); + } + + this.config = parts[0]; + if(parts.length == 2) { + this.input = parts[1]; + } + } + + public String getConfig() { + return config; + } + + public String getInput() { + return input; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + ConfigInput configInput = (ConfigInput) o; + + if (config != null ? !config.equals(configInput.config) : configInput.config != null) + return false; + if (input != null ? !input.equals(configInput.input) : configInput.input != null) + return false; + + return true; + } + + @Override + public int hashCode() { + int result = config != null ? config.hashCode() : 0; + result = 31 * result + (input != null ? input.hashCode() : 0); + return result; + } + + @Override + public String toString() { + if(input == null) { + return config; + } + + return config + "." + input; + } + } +} http://git-wip-us.apache.org/repos/asf/sqoop/blob/8362c73c/common/src/main/java/org/apache/sqoop/validation/Message.java ---------------------------------------------------------------------- diff --git a/common/src/main/java/org/apache/sqoop/validation/Message.java b/common/src/main/java/org/apache/sqoop/validation/Message.java index cb55b6a..3361b6f 100644 --- a/common/src/main/java/org/apache/sqoop/validation/Message.java +++ b/common/src/main/java/org/apache/sqoop/validation/Message.java @@ -21,7 +21,7 @@ package org.apache.sqoop.validation; * Validation message. * * Validation message have always two parts - severity and textual information about what - * is wrong. It can be associated with Input, Form or Configuration class. + * is wrong. It can be associated with Input, Config or ConfigurationGroup class. */ public class Message { private Status status; http://git-wip-us.apache.org/repos/asf/sqoop/blob/8362c73c/common/src/main/java/org/apache/sqoop/validation/Validation.java ---------------------------------------------------------------------- diff --git a/common/src/main/java/org/apache/sqoop/validation/Validation.java b/common/src/main/java/org/apache/sqoop/validation/Validation.java deleted file mode 100644 index fce6e88..0000000 --- a/common/src/main/java/org/apache/sqoop/validation/Validation.java +++ /dev/null @@ -1,228 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.sqoop.validation; - -import org.apache.sqoop.common.SqoopException; - -import java.lang.reflect.Field; -import java.util.HashMap; -import java.util.Map; - -/** - * Validation class. - * - * This class represents validations to given configuration object. - */ -public class Validation { - - // Configuration class that belongs to this validation - Class klass; - - // Entire validation status - Status status; - - // Status messages for various fields - Map<FormInput, Message> messages; - - public Validation(Class klass) { - this.klass = klass; - status = Status.getDefault(); - messages = new HashMap<FormInput, Message>(); - } - - public Validation(Status status, Map<FormInput, Message> messages) { - this.status = status; - this.messages = messages; - } - - public Status getStatus() { - return status; - } - - public Map<FormInput, Message> getMessages() { - return messages; - } - - /** - * Add message to form. - * - * @param status Severity of the message - * @param form Form name, must be defined in the class - * @param message Validation message - */ - public void addMessage(Status status, String form, String message) { - addMessage(status, form, null, message); - } - - /** - * Add message to input in one of the forms. - * - * @param status Severity of the message - * @param form Form name, must be defined in the class - * @param input Field name, must be defined in the form class - * @param message Validation message - */ - public void addMessage(Status status, String form, String input, String message ) { - if( klass == null) { - throw new SqoopException(ValidationError.VALIDATION_0001); - } - - assert form != null; - assert message != null; - - // Field for specified form - Field formField; - - // Load the form field and verify that it exists - try { - formField = klass.getDeclaredField(form); - } catch (NoSuchFieldException e) { - throw new SqoopException(ValidationError.VALIDATION_0002, - "Can't get form " + form + " from " + klass.getName(), e); - } - - // If this is form message, just save the message and continue - if(input == null) { - setMessage(status, form, input, message); - return; - } - - // Verify that specified input exists on the form - try { - formField.getType().getDeclaredField(input); - } catch (NoSuchFieldException e) { - throw new SqoopException(ValidationError.VALIDATION_0002, - "Can't get input " + input + " from form" + formField.getType().getName(), e); - } - - setMessage(status, form, input, message); - } - - private void setMessage(Status status, String form, String input, String message) { - this.status = Status.getWorstStatus(this.status, status); - messages.put(new FormInput(form, input), new Message(status, message)); - } - - public static class Message { - private Status status; - private String message; - - public Message(Status status, String message) { - this.status = status; - this.message = message; - } - - public Status getStatus() { - return status; - } - - public String getMessage() { - return message; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof Message)) return false; - - Message message1 = (Message) o; - - if (message != null ? !message.equals(message1.message) : message1.message != null) - return false; - if (status != message1.status) return false; - - return true; - } - - @Override - public int hashCode() { - int result = status != null ? status.hashCode() : 0; - result = 31 * result + (message != null ? message.hashCode() : 0); - return result; - } - - @Override - public String toString() { - return "{" + status.name() + ": " + message + "}"; - } - } - - public static class FormInput { - private String form; - private String input; - - public FormInput(String form, String input) { - this.form = form; - this.input = input; - } - - public FormInput(String formInput) { - assert formInput != null; - String []parts = formInput.split("\\."); - - if(formInput.isEmpty() || (parts.length != 1 && parts.length != 2)) { - throw new SqoopException(ValidationError.VALIDATION_0003, - "Specification " + formInput + " is not in valid format form.input"); - } - - this.form = parts[0]; - if(parts.length == 2) { - this.input = parts[1]; - } - } - - public String getForm() { - return form; - } - - public String getInput() { - return input; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - FormInput formInput = (FormInput) o; - - if (form != null ? !form.equals(formInput.form) : formInput.form != null) - return false; - if (input != null ? !input.equals(formInput.input) : formInput.input != null) - return false; - - return true; - } - - @Override - public int hashCode() { - int result = form != null ? form.hashCode() : 0; - result = 31 * result + (input != null ? input.hashCode() : 0); - return result; - } - - @Override - public String toString() { - if(input == null) { - return form; - } - - return form + "." + input; - } - } -} http://git-wip-us.apache.org/repos/asf/sqoop/blob/8362c73c/common/src/main/java/org/apache/sqoop/validation/ValidationError.java ---------------------------------------------------------------------- diff --git a/common/src/main/java/org/apache/sqoop/validation/ValidationError.java b/common/src/main/java/org/apache/sqoop/validation/ValidationError.java deleted file mode 100644 index ec64f10..0000000 --- a/common/src/main/java/org/apache/sqoop/validation/ValidationError.java +++ /dev/null @@ -1,52 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.sqoop.validation; - -import org.apache.sqoop.common.ErrorCode; - -/** - * - */ -public enum ValidationError implements ErrorCode { - - VALIDATION_0000("Unknown error"), - - VALIDATION_0001("Missing class declaration."), - - VALIDATION_0002("Usage of missing field"), - - VALIDATION_0003("Invalid representation of form and input field"), - - VALIDATION_0004("Can't find validator class"), - - ; - - private final String message; - - private ValidationError(String message) { - this.message = message; - } - - public String getCode() { - return name(); - } - - public String getMessage() { - return message; - } -} http://git-wip-us.apache.org/repos/asf/sqoop/blob/8362c73c/common/src/main/java/org/apache/sqoop/validation/ValidationResult.java ---------------------------------------------------------------------- diff --git a/common/src/main/java/org/apache/sqoop/validation/ValidationResult.java b/common/src/main/java/org/apache/sqoop/validation/ValidationResult.java deleted file mode 100644 index ae8f1d1..0000000 --- a/common/src/main/java/org/apache/sqoop/validation/ValidationResult.java +++ /dev/null @@ -1,98 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.sqoop.validation; - -import org.apache.sqoop.validation.validators.AbstractValidator; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Result of validation execution. - */ -public class ValidationResult { - - /** - * All messages for each named item. - */ - Map<String, List<Message>> messages; - - /** - * Overall status. - */ - Status status; - - public ValidationResult() { - messages = new HashMap<String, List<Message>>(); - status = Status.getDefault(); - } - - /** - * Add given validator result to this instance. - * - * @param name Full name of the validated object - * @param validator Executed validator - */ - public void addValidator(String name, AbstractValidator validator) { - if(validator.getStatus() == Status.getDefault()) { - return; - } - - status = Status.getWorstStatus(status, validator.getStatus()); - if(messages.containsKey(name)) { - messages.get(name).addAll(validator.getMessages()); - } else { - messages.put(name, validator.getMessages()); - } - } - - /** - * Merge results with another validation result. - * - * @param result Other validation result - */ - public void merge(ValidationResult result) { - messages.putAll(result.messages); - status = Status.getWorstStatus(status, result.status); - } - - /** - * Method to directly add messages for given name. - * - * This method will replace previous messages for given name. - * - * @param name Name of the entity - * @param messages List of messages associated with the name - */ - public void addMessages(String name, List<Message> messages) { - this.messages.put(name, messages); - - for(Message message : messages) { - this.status = Status.getWorstStatus(status, message.getStatus()); - } - } - - public Status getStatus() { - return status; - } - - public Map<String, List<Message>> getMessages() { - return messages; - } -} http://git-wip-us.apache.org/repos/asf/sqoop/blob/8362c73c/common/src/main/java/org/apache/sqoop/validation/ValidationRunner.java ---------------------------------------------------------------------- diff --git a/common/src/main/java/org/apache/sqoop/validation/ValidationRunner.java b/common/src/main/java/org/apache/sqoop/validation/ValidationRunner.java deleted file mode 100644 index 8ffc0d4..0000000 --- a/common/src/main/java/org/apache/sqoop/validation/ValidationRunner.java +++ /dev/null @@ -1,176 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.sqoop.validation; - -import org.apache.sqoop.common.SqoopException; -import org.apache.sqoop.model.ConfigurationClass; -import org.apache.sqoop.model.Form; -import org.apache.sqoop.model.FormClass; -import org.apache.sqoop.model.FormUtils; -import org.apache.sqoop.model.Input; -import org.apache.sqoop.model.Validator; -import org.apache.sqoop.utils.ClassUtils; -import org.apache.sqoop.validation.validators.AbstractValidator; - -import java.lang.reflect.Field; -import java.util.HashMap; -import java.util.Map; - -/** - * Validation runner that will run validators associated with given configuration - * class or form object. - * - * Execution follows following rules: - * * Run children first (Inputs -> Form -> Class) - * * If any children is not suitable (canProceed = false), skip running parent - * - * Which means that form validator don't have to repeat it's input validators as it will - * be never called if the input's are not valid. Similarly Class validators won't be called - * unless all forms will pass validators. - */ -public class ValidationRunner { - - /** - * Private cache of instantiated validators. - * - * We're expecting that this cache will be very small as the number of possible validators - * is driven to high extent by the number of connectors and hence we don't have a cache - * eviction at the moment. - */ - private Map<Class<? extends AbstractValidator>, AbstractValidator> cache; - - public ValidationRunner() { - cache = new HashMap<Class<? extends AbstractValidator>, AbstractValidator>(); - } - - /** - * Validate given configuration instance. - * - * @param config Configuration instance - * @return - */ - public ValidationResult validate(Object config) { - ValidationResult result = new ValidationResult(); - ConfigurationClass globalAnnotation = FormUtils.getConfigurationClassAnnotation(config, true); - - // Iterate over all declared form and call their validators - for (Field field : config.getClass().getDeclaredFields()) { - field.setAccessible(true); - - Form formAnnotation = FormUtils.getFormAnnotation(field, false); - if(formAnnotation == null) { - continue; - } - - String formName = FormUtils.getName(field, formAnnotation); - ValidationResult r = validateForm(formName, FormUtils.getFieldValue(field, config)); - result.merge(r); - } - - // Call class validator only as long as we are in suitable state - if(result.getStatus().canProceed()) { - ValidationResult r = validateArray("", config, globalAnnotation.validators()); - result.merge(r); - } - - return result; - } - - /** - * Validate given form instance. - * - * @param formName Form's name to build full name for all inputs. - * @param form Form instance - * @return - */ - public ValidationResult validateForm(String formName, Object form) { - ValidationResult result = new ValidationResult(); - FormClass formAnnotation = FormUtils.getFormClassAnnotation(form, true); - - // Iterate over all declared inputs and call their validators - for (Field field : form.getClass().getDeclaredFields()) { - Input inputAnnotation = FormUtils.getInputAnnotation(field, false); - if(inputAnnotation == null) { - continue; - } - - String name = formName + "." + FormUtils.getName(field, inputAnnotation); - - ValidationResult r = validateArray(name, FormUtils.getFieldValue(field, form), inputAnnotation.validators()); - result.merge(r); - } - - // Call form validator only as long as we are in suitable state - if(result.getStatus().canProceed()) { - ValidationResult r = validateArray(formName, form, formAnnotation.validators()); - result.merge(r); - } - - return result; - } - - /** - * Execute array of validators on given object (can be input/form/class). - * - * @param name Full name of the object - * @param object Input, Form or Class instance - * @param validators Validators array - * @return - */ - private ValidationResult validateArray(String name, Object object, Validator[] validators) { - ValidationResult result = new ValidationResult(); - - for (Validator validator : validators) { - AbstractValidator v = executeValidator(object, validator); - result.addValidator(name, v); - } - - return result; - } - - /** - * Execute single validator. - * - * @param object Input, Form or Class instance - * @param validator Validator annotation - * @return - */ - private AbstractValidator executeValidator(Object object, Validator validator) { - // Try to get validator instance from the cache - AbstractValidator instance = cache.get(validator.value()); - - if(instance == null) { - instance = (AbstractValidator) ClassUtils.instantiate(validator.value()); - - // This could happen if we would be missing some connector's jars on our classpath - if(instance == null) { - throw new SqoopException(ValidationError.VALIDATION_0004, validator.value().getName()); - } - - cache.put(validator.value(), instance); - } else { - instance.reset(); - } - - instance.setStringArgument(validator.strArg()); - instance.validate(object); - return instance; - } - - -}