You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sqoop.apache.org by ab...@apache.org on 2014/10/03 08:53:26 UTC
[12/13] SQOOP-1498: Sqoop2: Repository Object refactoring (objects
prefixed with M)
http://git-wip-us.apache.org/repos/asf/sqoop/blob/f63c080d/common/src/main/java/org/apache/sqoop/json/util/ConfigSerialization.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/json/util/ConfigSerialization.java b/common/src/main/java/org/apache/sqoop/json/util/ConfigSerialization.java
new file mode 100644
index 0000000..cec46f6
--- /dev/null
+++ b/common/src/main/java/org/apache/sqoop/json/util/ConfigSerialization.java
@@ -0,0 +1,226 @@
+/**
+ * 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;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.sqoop.common.SqoopException;
+import org.apache.sqoop.model.MBooleanInput;
+import org.apache.sqoop.model.MEnumInput;
+import org.apache.sqoop.model.MConfig;
+import org.apache.sqoop.model.MConfigType;
+import org.apache.sqoop.model.MInput;
+import org.apache.sqoop.model.MInputType;
+import org.apache.sqoop.model.MIntegerInput;
+import org.apache.sqoop.model.MMapInput;
+import org.apache.sqoop.model.MStringInput;
+import org.json.simple.JSONArray;
+import org.json.simple.JSONObject;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Convenient static methods for serializing config objects.
+ */
+public final class ConfigSerialization {
+
+ public static final String ALL = "all";
+ public static final String ID = "id";
+ public static final String NAME = "name";
+ public static final String VERSION = "version";
+ public static final String CLASS = "class";
+ public static final String ENABLED = "enabled";
+ public static final String CREATION_USER = "creation-user";
+ public static final String CREATION_DATE = "creation-date";
+ public static final String UPDATE_USER = "update-user";
+ public static final String UPDATE_DATE = "update-date";
+ // TODO(VB): Move these constants to connector bean
+ public static final String CONNECTOR_LINK_CONFIG = "link-config";
+ public static final String CONNECTOR_JOB_CONFIG = "job-config";
+ // TODO:move these configs to driver bean
+ public static final String DRIVER_VERSION = "driver-version";
+ public static final String DRIVER_CONFIG = "driver-config";
+
+ 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 CONFIG_INPUT_NAME = "name";
+ public static final String CONFIG_INPUT_TYPE = "type";
+ public static final String CONFIG_INPUT_SENSITIVE = "sensitive";
+ public static final String CONFIG_INPUT_SIZE = "size";
+ public static final String CONFIG_INPUT_VALUE = "value";
+ public static final String CONFIG_INPUT_VALUES = "values";
+
+ /**
+ * Transform given list of configs to JSON Array object.
+ *
+ * @param mConfigs List of configs.
+ * @return JSON object with serialized config of the list.
+ */
+ @SuppressWarnings("unchecked")
+ public static JSONArray extractConfigList(List<MConfig> mConfigs, boolean skipSensitive) {
+ JSONArray configs = new JSONArray();
+
+ for (MConfig mConfig : mConfigs) {
+ configs.add(extractConfig(mConfig, skipSensitive));
+ }
+
+ return configs;
+ }
+
+ /**
+ * Transform given config to JSON Object.
+ *
+ * @param mConfig Given MConfig instance
+ * @param skipSensitive conditionally add sensitive input values
+ * @return Serialized JSON object.
+ */
+ @SuppressWarnings("unchecked")
+ static JSONObject extractConfig(MConfig mConfig, boolean skipSensitive) {
+ JSONObject config = new JSONObject();
+ config.put(ID, mConfig.getPersistenceId());
+ config.put(CONFIG_NAME, mConfig.getName());
+ config.put(CONFIG_TYPE, MConfigType.LINK.toString());
+ JSONArray mInputs = new JSONArray();
+ config.put(CONFIG_INPUTS, mInputs);
+
+ for (MInput<?> mInput : mConfig.getInputs()) {
+ JSONObject input = new JSONObject();
+ input.put(ID, mInput.getPersistenceId());
+ input.put(CONFIG_INPUT_NAME, mInput.getName());
+ input.put(CONFIG_INPUT_TYPE, mInput.getType().toString());
+ input.put(CONFIG_INPUT_SENSITIVE, mInput.isSensitive());
+
+ // String specific serialization
+ if (mInput.getType() == MInputType.STRING) {
+ input.put(CONFIG_INPUT_SIZE,
+ ((MStringInput)mInput).getMaxLength());
+ }
+
+ // Enum specific serialization
+ if(mInput.getType() == MInputType.ENUM) {
+ input.put(CONFIG_INPUT_VALUES,
+ StringUtils.join(((MEnumInput)mInput).getValues(), ","));
+ }
+
+ // Serialize value if is there
+ // Skip if sensitive
+ if (!mInput.isEmpty() && !(skipSensitive && mInput.isSensitive())) {
+ if (mInput.getType() == MInputType.MAP) {
+ input.put(CONFIG_INPUT_VALUE, mInput.getValue());
+ } else {
+ input.put(CONFIG_INPUT_VALUE, mInput.getUrlSafeValueString());
+ }
+ }
+
+ mInputs.add(input);
+ }
+
+ return config;
+ }
+
+ /**
+ * 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) {
+ List<MConfig> mConfigs = new ArrayList<MConfig>();
+
+ for (int i = 0; i < configs.size(); i++) {
+ mConfigs.add(restoreConfig((JSONObject) configs.get(i)));
+ }
+
+ return mConfigs;
+ }
+
+ /**
+ * Restore one MConfig from JSON Object.
+ *
+ * @param config JSON representation of the MConfig.
+ * @return Restored MConfig.
+ */
+ static MConfig restoreConfig(JSONObject config) {
+ JSONArray inputs = (JSONArray) config.get(CONFIG_INPUTS);
+
+ List<MInput<?>> mInputs = new ArrayList<MInput<?>>();
+ for (int i = 0; i < inputs.size(); i++) {
+ JSONObject input = (JSONObject) inputs.get(i);
+ MInputType type =
+ MInputType.valueOf((String) input.get(CONFIG_INPUT_TYPE));
+ String name = (String) input.get(CONFIG_INPUT_NAME);
+ Boolean sensitive = (Boolean) input.get(CONFIG_INPUT_SENSITIVE);
+ MInput mInput = null;
+ switch (type) {
+ case STRING: {
+ long size = (Long) input.get(CONFIG_INPUT_SIZE);
+ mInput = new MStringInput(name, sensitive.booleanValue(), (short) size);
+ break;
+ }
+ case MAP: {
+ mInput = new MMapInput(name, sensitive.booleanValue());
+ break;
+ }
+ case INTEGER: {
+ mInput = new MIntegerInput(name, sensitive.booleanValue());
+ break;
+ }
+ case BOOLEAN: {
+ mInput = new MBooleanInput(name, sensitive.booleanValue());
+ break;
+ }
+ case ENUM: {
+ String values = (String) input.get(CONFIG_INPUT_VALUES);
+ mInput = new MEnumInput(name, sensitive.booleanValue(), values.split(","));
+ break;
+ }
+ }
+
+ // Propagate config ID
+ mInput.setPersistenceId((Long)input.get(ID));
+
+ // Propagate config optional value
+ if(input.containsKey(CONFIG_INPUT_VALUE)) {
+ switch (type) {
+ case MAP:
+ try {
+ mInput.setValue((Map<String, String>)input.get(CONFIG_INPUT_VALUE));
+ } catch (ClassCastException e) {
+ throw new SqoopException(SerializationError.SERIALIZATION_001, name + " requires a 'map' value.");
+ }
+ break;
+ default:
+ mInput.restoreFromUrlSafeValueString(
+ (String) input.get(CONFIG_INPUT_VALUE));
+ break;
+ }
+ }
+ mInputs.add(mInput);
+ }
+
+ MConfig mConfig = new MConfig((String) config.get(CONFIG_NAME), mInputs);
+ mConfig.setPersistenceId((Long) config.get(ID));
+ return mConfig;
+ }
+
+ private ConfigSerialization() {
+ // Do not instantiate
+ }
+}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/f63c080d/common/src/main/java/org/apache/sqoop/json/util/FormSerialization.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/json/util/FormSerialization.java b/common/src/main/java/org/apache/sqoop/json/util/FormSerialization.java
deleted file mode 100644
index 77f6191..0000000
--- a/common/src/main/java/org/apache/sqoop/json/util/FormSerialization.java
+++ /dev/null
@@ -1,223 +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.json.util;
-
-import org.apache.commons.lang.StringUtils;
-import org.apache.sqoop.common.SqoopException;
-import org.apache.sqoop.model.MBooleanInput;
-import org.apache.sqoop.model.MEnumInput;
-import org.apache.sqoop.model.MForm;
-import org.apache.sqoop.model.MFormType;
-import org.apache.sqoop.model.MInput;
-import org.apache.sqoop.model.MInputType;
-import org.apache.sqoop.model.MIntegerInput;
-import org.apache.sqoop.model.MMapInput;
-import org.apache.sqoop.model.MStringInput;
-import org.json.simple.JSONArray;
-import org.json.simple.JSONObject;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Convenient static methods for serializing forms.
- */
-public final class FormSerialization {
-
- public static final String ALL = "all";
- public static final String ID = "id";
- public static final String NAME = "name";
- public static final String VERSION = "version";
- public static final String DRIVER_VERSION = "driver-version";
- public static final String CLASS = "class";
- public static final String ENABLED = "enabled";
- public static final String CREATION_USER = "creation-user";
- public static final String CREATION_DATE = "creation-date";
- public static final String UPDATE_USER = "update-user";
- public static final String UPDATE_DATE = "update-date";
- public static final String CON_FORMS = "con-forms";
- public static final String JOB_FORMS = "job-forms";
-
- public static final String FORM_NAME = "name";
- public static final String FORM_TYPE = "type";
- public static final String FORM_INPUTS = "inputs";
- public static final String FORM_INPUT_NAME = "name";
- public static final String FORM_INPUT_TYPE = "type";
- public static final String FORM_INPUT_SENSITIVE = "sensitive";
- public static final String FORM_INPUT_SIZE = "size";
- public static final String FORM_INPUT_VALUE = "value";
- public static final String FORM_INPUT_VALUES = "values";
-
- /**
- * Transform given list of forms to JSON Array object.
- *
- * @param mForms List of forms.
- * @return JSON object with serialized form of the list.
- */
- @SuppressWarnings("unchecked")
- public static JSONArray extractForms(List<MForm> mForms, boolean skipSensitive) {
- JSONArray forms = new JSONArray();
-
- for (MForm mForm : mForms) {
- forms.add(extractForm(mForm, skipSensitive));
- }
-
- return forms;
- }
-
- /**
- * Transform given form to JSON Object.
- *
- * @param mForm Given MForm instance
- * @param skipSensitive conditionally add sensitive input values
- * @return Serialized JSON object.
- */
- @SuppressWarnings("unchecked")
- public static JSONObject extractForm(MForm mForm, boolean skipSensitive) {
- JSONObject form = new JSONObject();
- form.put(ID, mForm.getPersistenceId());
- form.put(FORM_NAME, mForm.getName());
- form.put(FORM_TYPE, MFormType.CONNECTION.toString());
- JSONArray mInputs = new JSONArray();
- form.put(FORM_INPUTS, mInputs);
-
- for (MInput<?> mInput : mForm.getInputs()) {
- JSONObject input = new JSONObject();
- input.put(ID, mInput.getPersistenceId());
- input.put(FORM_INPUT_NAME, mInput.getName());
- input.put(FORM_INPUT_TYPE, mInput.getType().toString());
- input.put(FORM_INPUT_SENSITIVE, mInput.isSensitive());
-
- // String specific serialization
- if (mInput.getType() == MInputType.STRING) {
- input.put(FORM_INPUT_SIZE,
- ((MStringInput)mInput).getMaxLength());
- }
-
- // Enum specific serialization
- if(mInput.getType() == MInputType.ENUM) {
- input.put(FORM_INPUT_VALUES,
- StringUtils.join(((MEnumInput)mInput).getValues(), ","));
- }
-
- // Serialize value if is there
- // Skip if sensitive
- if (!mInput.isEmpty() && !(skipSensitive && mInput.isSensitive())) {
- if (mInput.getType() == MInputType.MAP) {
- input.put(FORM_INPUT_VALUE, mInput.getValue());
- } else {
- input.put(FORM_INPUT_VALUE, mInput.getUrlSafeValueString());
- }
- }
-
- mInputs.add(input);
- }
-
- return form;
- }
-
- /**
- * Restore List of MForms from JSON Array.
- *
- * @param forms JSON array representing list of MForms
- * @return Restored list of MForms
- */
- public static List<MForm> restoreForms(JSONArray forms) {
- List<MForm> mForms = new ArrayList<MForm>();
-
- for (int i = 0; i < forms.size(); i++) {
- mForms.add(restoreForm((JSONObject) forms.get(i)));
- }
-
- return mForms;
- }
-
- /**
- * Restore one MForm from JSON Object.
- *
- * @param form JSON representation of the MForm.
- * @return Restored MForm.
- */
- public static MForm restoreForm(JSONObject form) {
- JSONArray inputs = (JSONArray) form.get(FORM_INPUTS);
-
- List<MInput<?>> mInputs = new ArrayList<MInput<?>>();
- for (int i = 0; i < inputs.size(); i++) {
- JSONObject input = (JSONObject) inputs.get(i);
- MInputType type =
- MInputType.valueOf((String) input.get(FORM_INPUT_TYPE));
- String name = (String) input.get(FORM_INPUT_NAME);
- Boolean sensitive = (Boolean) input.get(FORM_INPUT_SENSITIVE);
- MInput mInput = null;
- switch (type) {
- case STRING: {
- long size = (Long) input.get(FORM_INPUT_SIZE);
- mInput = new MStringInput(name, sensitive.booleanValue(), (short) size);
- break;
- }
- case MAP: {
- mInput = new MMapInput(name, sensitive.booleanValue());
- break;
- }
- case INTEGER: {
- mInput = new MIntegerInput(name, sensitive.booleanValue());
- break;
- }
- case BOOLEAN: {
- mInput = new MBooleanInput(name, sensitive.booleanValue());
- break;
- }
- case ENUM: {
- String values = (String) input.get(FORM_INPUT_VALUES);
- mInput = new MEnumInput(name, sensitive.booleanValue(), values.split(","));
- break;
- }
- }
-
- // Propagate form ID
- mInput.setPersistenceId((Long)input.get(ID));
-
- // Propagate form optional value
- if(input.containsKey(FORM_INPUT_VALUE)) {
- switch (type) {
- case MAP:
- try {
- mInput.setValue((Map<String, String>)input.get(FORM_INPUT_VALUE));
- } catch (ClassCastException e) {
- throw new SqoopException(SerializationError.SERIALIZATION_001, name + " requires a 'map' value.");
- }
- break;
- default:
- mInput.restoreFromUrlSafeValueString(
- (String) input.get(FORM_INPUT_VALUE));
- break;
- }
- }
- mInputs.add(mInput);
- }
-
- MForm mForm = new MForm((String) form.get(FORM_NAME), mInputs);
- mForm.setPersistenceId((Long) form.get(ID));
- return mForm;
- }
-
- private FormSerialization() {
- // Do not instantiate
- }
-}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/f63c080d/common/src/main/java/org/apache/sqoop/json/util/ResourceBundleSerialization.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/json/util/ResourceBundleSerialization.java b/common/src/main/java/org/apache/sqoop/json/util/ResourceBundleSerialization.java
index 20ee5f3..f27d81d 100644
--- a/common/src/main/java/org/apache/sqoop/json/util/ResourceBundleSerialization.java
+++ b/common/src/main/java/org/apache/sqoop/json/util/ResourceBundleSerialization.java
@@ -43,7 +43,6 @@ public final class ResourceBundleSerialization {
for (ResourceBundle bundle : bundles) {
array.add(extractResourceBundle(bundle));
}
-
return array;
}
@@ -58,7 +57,6 @@ public final class ResourceBundleSerialization {
return json;
}
- @SuppressWarnings("unchecked")
public static List<ResourceBundle> restoreResourceBundles(JSONArray array) {
List<ResourceBundle> bundles = new LinkedList<ResourceBundle>();
for (Object item : array) {
http://git-wip-us.apache.org/repos/asf/sqoop/blob/f63c080d/common/src/main/java/org/apache/sqoop/model/Config.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/model/Config.java b/common/src/main/java/org/apache/sqoop/model/Config.java
new file mode 100644
index 0000000..46e7268
--- /dev/null
+++ b/common/src/main/java/org/apache/sqoop/model/Config.java
@@ -0,0 +1,28 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sqoop.model;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Denote config in Configuration class
+ */
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Config {
+}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/f63c080d/common/src/main/java/org/apache/sqoop/model/ConfigClass.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/model/ConfigClass.java b/common/src/main/java/org/apache/sqoop/model/ConfigClass.java
new file mode 100644
index 0000000..f925759
--- /dev/null
+++ b/common/src/main/java/org/apache/sqoop/model/ConfigClass.java
@@ -0,0 +1,45 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sqoop.model;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Denote configuration class
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface ConfigClass {
+
+ /**
+ * Default size for Inputs in this config.
+ *
+ * @return
+ */
+ short defaultSize() default -1;
+
+ /**
+ * List of validators associated with this config.
+ *
+ * @return
+ */
+ Validator[] validators() default {};
+}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/f63c080d/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
new file mode 100644
index 0000000..290e7fc
--- /dev/null
+++ b/common/src/main/java/org/apache/sqoop/model/ConfigUtils.java
@@ -0,0 +1,565 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sqoop.model;
+
+import org.apache.sqoop.common.SqoopException;
+import org.apache.sqoop.utils.ClassUtils;
+import org.apache.sqoop.validation.Message;
+import org.apache.sqoop.validation.Status;
+import org.apache.sqoop.validation.ConfigValidator;
+import org.apache.sqoop.validation.ConfigValidationResult;
+import org.json.simple.JSONObject;
+import org.json.simple.JSONValue;
+
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Util class for transforming data from correctly annotated configuration
+ * objects to different structures and vice-versa.
+ *
+ * TODO: This class should see some overhaul into more reusable code, especially expose and re-use the methods at the end.
+ */
+public class ConfigUtils {
+
+ /**
+ * Transform correctly annotated configuration object to corresponding
+ * list of configs.
+ *
+ * Configs will be order according to the occurrence in the configuration
+ * class. Inputs will be also ordered based on occurrence.
+ *
+ * @param configuration Annotated arbitrary configuration object
+ * @return Corresponding list of configs
+ */
+ public static List<MConfig> toConfigs(Object configuration) {
+ return toConfigs(configuration.getClass(), configuration);
+ }
+
+ public static List<MConfig> toConfigs(Class klass) {
+ return toConfigs(klass, null);
+ }
+
+ @SuppressWarnings("unchecked")
+ public static List<MConfig> toConfigs(Class klass, Object configuration) {
+ ConfigurationClass configurationClass =
+ (ConfigurationClass)klass.getAnnotation(ConfigurationClass.class);
+
+ // Each configuration object must have this class annotation
+ if(configurationClass == null) {
+ throw new SqoopException(ModelError.MODEL_003,
+ "Missing annotation ConfigurationClass on class " + klass.getName());
+ }
+
+ List<MConfig> configs = new LinkedList<MConfig>();
+
+ // Iterate over all declared fields
+ for (Field field : klass.getDeclaredFields()) {
+ field.setAccessible(true);
+
+ String formName = field.getName();
+
+ // Each field that should be part of user input should have Input
+ // annotation.
+ Config formAnnotation = field.getAnnotation(Config.class);
+
+ if(formAnnotation != null) {
+ Class type = field.getType();
+
+ Object value = null;
+ if(configuration != null) {
+ try {
+ value = field.get(configuration);
+ } catch (IllegalAccessException e) {
+ throw new SqoopException(ModelError.MODEL_005,
+ "Can't retrieve value from " + field.getName(), e);
+ }
+ }
+
+ configs.add(toConfig(formName, type, value));
+ }
+ }
+
+ return configs;
+ }
+
+ @SuppressWarnings("unchecked")
+ private static MConfig toConfig(String formName, Class klass, Object object) {
+ ConfigClass global =
+ (ConfigClass)klass.getAnnotation(ConfigClass.class);
+
+ // Each configuration object must have this class annotation
+ if(global == null) {
+ throw new SqoopException(ModelError.MODEL_003,
+ "Missing annotation ConfigClass on class " + klass.getName());
+ }
+
+ // Intermediate list of inputs
+ List<MInput<?>> inputs = new LinkedList<MInput<?>>();
+
+ // Iterate over all declared fields
+ for (Field field : klass.getDeclaredFields()) {
+ field.setAccessible(true);
+
+ String fieldName = field.getName();
+ String inputName = formName + "." + fieldName;
+
+ // Each field that should be part of user input should have Input
+ // annotation.
+ Input inputAnnotation = field.getAnnotation(Input.class);
+
+ if(inputAnnotation != null) {
+ boolean sensitive = inputAnnotation.sensitive();
+ short maxLen = inputAnnotation.size();
+ Class type = field.getType();
+
+ MInput input;
+
+ // We need to support NULL, so we do not support primitive types
+ if(type.isPrimitive()) {
+ throw new SqoopException(ModelError.MODEL_007,
+ "Detected primitive type " + type + " for field " + fieldName);
+ }
+
+ // Instantiate corresponding MInput<?> structure
+ if(type == String.class) {
+ input = new MStringInput(inputName, sensitive, maxLen);
+ } else if (type.isAssignableFrom(Map.class)) {
+ input = new MMapInput(inputName, sensitive);
+ } else if(type == Integer.class) {
+ input = new MIntegerInput(inputName, sensitive);
+ } else if(type == Boolean.class) {
+ input = new MBooleanInput(inputName, sensitive);
+ } else if(type.isEnum()) {
+ input = new MEnumInput(inputName, sensitive, ClassUtils.getEnumStrings(type));
+ } else {
+ throw new SqoopException(ModelError.MODEL_004,
+ "Unsupported type " + type.getName() + " for input " + fieldName);
+ }
+
+ // Move value if it's present in original configuration object
+ if(object != null) {
+ Object value;
+ try {
+ value = field.get(object);
+ } catch (IllegalAccessException e) {
+ throw new SqoopException(ModelError.MODEL_005,
+ "Can't retrieve value from " + field.getName(), e);
+ }
+ if(value == null) {
+ input.setEmpty();
+ } else {
+ input.setValue(value);
+ }
+ }
+
+ inputs.add(input);
+ }
+ }
+
+ return new MConfig(formName, inputs);
+ }
+
+ /**
+ * Move config values from config list into corresponding configuration object.
+ *
+ * @param configs Input config list
+ * @param configuration Output configuration object
+ */
+ public static void fromConfigs(List<MConfig> configs, Object configuration) {
+ Class klass = configuration.getClass();
+
+ for(MConfig config : configs) {
+ Field configField;
+ try {
+ configField = klass.getDeclaredField(config.getName());
+ } catch (NoSuchFieldException e) {
+ throw new SqoopException(ModelError.MODEL_006,
+ "Missing field " + config.getName() + " on config class " + klass.getCanonicalName(), e);
+ }
+
+ // We need to access this field even if it would be declared as private
+ configField.setAccessible(true);
+
+ Class configClass = configField.getType();
+ Object newValue = ClassUtils.instantiate(configClass);
+
+ if(newValue == null) {
+ throw new SqoopException(ModelError.MODEL_006,
+ "Can't instantiate new config " + configClass);
+ }
+
+ for(MInput input : config.getInputs()) {
+ String[] splitNames = input.getName().split("\\.");
+ if(splitNames.length != 2) {
+ throw new SqoopException(ModelError.MODEL_009,
+ "Invalid name: " + input.getName());
+ }
+
+ String inputName = splitNames[1];
+ // TODO(jarcec): Names structures fix, handle error cases
+ Field inputField;
+ try {
+ inputField = configClass.getDeclaredField(inputName);
+ } catch (NoSuchFieldException e) {
+ throw new SqoopException(ModelError.MODEL_006,
+ "Missing field " + input.getName(), e);
+ }
+
+ // We need to access this field even if it would be declared as private
+ inputField.setAccessible(true);
+
+ try {
+ if(input.isEmpty()) {
+ inputField.set(newValue, null);
+ } else {
+ if (input.getType() == MInputType.ENUM) {
+ inputField.set(newValue, Enum.valueOf((Class<? extends Enum>)inputField.getType(), (String) input.getValue()));
+ } else {
+ inputField.set(newValue, input.getValue());
+ }
+ }
+ } catch (IllegalAccessException e) {
+ throw new SqoopException(ModelError.MODEL_005,
+ "Issue with field " + inputField.getName(), e);
+ }
+ }
+
+ try {
+ configField.set(configuration, newValue);
+ } catch (IllegalAccessException e) {
+ throw new SqoopException(ModelError.MODEL_005,
+ "Issue with field " + configField.getName(), e);
+ }
+ }
+ }
+
+ /**
+ * Apply validations on the configs.
+ *
+ * @param configs Configs that should be updated
+ * @param validation Validation that we should apply
+ */
+ public static void applyValidation(List<MConfig> configs, ConfigValidator validation) {
+ Map<ConfigValidator.ConfigInput, ConfigValidator.Message> messages = validation.getMessages();
+
+ for(MConfig config : configs) {
+ applyValidation(config, messages);
+
+ for(MInput input : config.getInputs()) {
+ applyValidation(input, messages);
+ }
+ }
+ }
+
+ /**
+ * Apply validation on given validated element.
+ *
+ * @param element Element on what we're applying the validations
+ * @param messages Map of all validation messages
+ */
+ public static void applyValidation(MValidatedElement element, Map<ConfigValidator.ConfigInput, ConfigValidator.Message> messages) {
+ ConfigValidator.ConfigInput name = new ConfigValidator.ConfigInput(element.getName());
+
+ if(messages.containsKey(name)) {
+ ConfigValidator.Message message = messages.get(name);
+ element.addValidationMessage(new Message(message.getStatus(), message.getMessage()));
+ } else {
+ element.addValidationMessage(new Message(Status.getDefault(), null));
+ }
+ }
+
+
+ /**
+ * Apply given validations on list of configs.
+ *
+ * @param configs
+ * @param result
+ */
+ public static void applyValidation(List<MConfig> configs, ConfigValidationResult result) {
+ for(MConfig config : configs) {
+ applyValidation(config, result);
+
+ for(MInput input : config.getInputs()) {
+ applyValidation(input, result);
+ }
+ }
+ }
+
+ /**
+ * Apply validation messages on given element.
+ *
+ * Element's state will be set to default if there are no associated messages.
+ *
+ * @param element
+ * @param result
+ */
+ public static void applyValidation(MValidatedElement element, ConfigValidationResult result) {
+ List<Message> messages = result.getMessages().get(element.getName());
+
+ if(messages != null) {
+ element.setValidationMessages(messages);
+ } else {
+ element.resetValidationMessages();
+ }
+ }
+
+ /**
+ * Convert configuration object to JSON. Only filled properties are serialized,
+ * properties with null value are skipped.
+ *
+ * @param configuration Correctly annotated configuration object
+ * @return String of JSON representation
+ */
+ @SuppressWarnings("unchecked")
+ public static String toJson(Object configuration) {
+ Class klass = configuration.getClass();
+
+ ConfigurationClass configurationClass =
+ (ConfigurationClass)klass.getAnnotation(ConfigurationClass.class);
+
+ // Each configuration object must have this class annotation
+ if(configurationClass == null) {
+ throw new SqoopException(ModelError.MODEL_003,
+ "Missing annotation ConfigurationGroup on class " + klass.getName());
+ }
+
+ JSONObject jsonOutput = new JSONObject();
+
+ // Iterate over all declared fields
+ for (Field formField : klass.getDeclaredFields()) {
+ formField.setAccessible(true);
+ String formName = formField.getName();
+
+ // We're processing only config validations
+ Config formAnnotation = formField.getAnnotation(Config.class);
+ if(formAnnotation == null) {
+ continue;
+ }
+
+ Object formValue;
+ try {
+ formValue = formField.get(configuration);
+ } catch (IllegalAccessException e) {
+ throw new SqoopException(ModelError.MODEL_005,
+ "Issue with field " + formName, e);
+ }
+
+ JSONObject jsonConfig = new JSONObject();
+
+ // Now process each input on the config
+ for(Field inputField : formField.getType().getDeclaredFields()) {
+ inputField.setAccessible(true);
+ String inputName = inputField.getName();
+
+ Object value;
+ try {
+ value = inputField.get(formValue);
+ } catch (IllegalAccessException e) {
+ throw new SqoopException(ModelError.MODEL_005,
+ "Issue with field " + formName + "." + inputName, e);
+ }
+
+ Input inputAnnotation = inputField.getAnnotation(Input.class);
+
+ // Do not serialize all values
+ if(inputAnnotation != null && value != null) {
+ Class type = inputField.getType();
+
+ // We need to support NULL, so we do not support primitive types
+ if(type.isPrimitive()) {
+ throw new SqoopException(ModelError.MODEL_007,
+ "Detected primitive type " + type + " for field " + formName + "." + inputName);
+ }
+
+ if(type == String.class) {
+ jsonConfig.put(inputName, value);
+ } else if (type.isAssignableFrom(Map.class)) {
+ JSONObject map = new JSONObject();
+ for(Object key : ((Map)value).keySet()) {
+ map.put(key, ((Map)value).get(key));
+ }
+ jsonConfig.put(inputName, map);
+ } else if(type == Integer.class) {
+ jsonConfig.put(inputName, value);
+ } else if(type.isEnum()) {
+ jsonConfig.put(inputName, value.toString());
+ } else if(type == Boolean.class) {
+ jsonConfig.put(inputName, value);
+ }else {
+ throw new SqoopException(ModelError.MODEL_004,
+ "Unsupported type " + type.getName() + " for input " + formName + "." + inputName);
+ }
+ }
+ }
+
+ jsonOutput.put(formName, jsonConfig);
+ }
+
+ return jsonOutput.toJSONString();
+ }
+
+ /**
+ * Parse given input JSON string and move it's values to given configuration
+ * object.
+ *
+ * @param json JSON representation of the configuration object
+ * @param configuration ConfigurationGroup object to be filled
+ */
+ public static void fillValues(String json, Object configuration) {
+ Class klass = configuration.getClass();
+
+ JSONObject jsonConfigs = (JSONObject) JSONValue.parse(json);
+
+ for(Field configField : klass.getDeclaredFields()) {
+ configField.setAccessible(true);
+ String configName = configField.getName();
+
+ // We're processing only config validations
+ Config formAnnotation = configField.getAnnotation(Config.class);
+ if(formAnnotation == null) {
+ continue;
+ }
+
+ try {
+ configField.set(configuration, configField.getType().newInstance());
+ } catch (Exception e) {
+ throw new SqoopException(ModelError.MODEL_005,
+ "Issue with field " + configName, e);
+ }
+
+ JSONObject jsonInputs = (JSONObject) jsonConfigs.get(configField.getName());
+ if(jsonInputs == null) {
+ continue;
+ }
+
+ Object configValue;
+ try {
+ configValue = configField.get(configuration);
+ } catch (IllegalAccessException e) {
+ throw new SqoopException(ModelError.MODEL_005,
+ "Issue with field " + configName, e);
+ }
+
+ for(Field inputField : configField.getType().getDeclaredFields()) {
+ inputField.setAccessible(true);
+ String inputName = inputField.getName();
+
+ Input inputAnnotation = inputField.getAnnotation(Input.class);
+
+ if(inputAnnotation == null || jsonInputs.get(inputName) == null) {
+ try {
+ inputField.set(configValue, null);
+ } catch (IllegalAccessException e) {
+ throw new SqoopException(ModelError.MODEL_005,
+ "Issue with field " + configName + "." + inputName, e);
+ }
+ continue;
+ }
+
+ Class type = inputField.getType();
+
+ try {
+ if(type == String.class) {
+ inputField.set(configValue, jsonInputs.get(inputName));
+ } else if (type.isAssignableFrom(Map.class)) {
+ Map<String, String> map = new HashMap<String, String>();
+ JSONObject jsonObject = (JSONObject) jsonInputs.get(inputName);
+ for(Object key : jsonObject.keySet()) {
+ map.put((String)key, (String)jsonObject.get(key));
+ }
+ inputField.set(configValue, map);
+ } else if(type == Integer.class) {
+ inputField.set(configValue, ((Long)jsonInputs.get(inputName)).intValue());
+ } else if(type.isEnum()) {
+ inputField.set(configValue, Enum.valueOf((Class<? extends Enum>) inputField.getType(), (String) jsonInputs.get(inputName)));
+ } else if(type == Boolean.class) {
+ inputField.set(configValue, (Boolean) jsonInputs.get(inputName));
+ }else {
+ throw new SqoopException(ModelError.MODEL_004,
+ "Unsupported type " + type.getName() + " for input " + configName + "." + inputName);
+ }
+ } catch (IllegalAccessException e) {
+ throw new SqoopException(ModelError.MODEL_005,
+ "Issue with field " + configName + "." + inputName, e);
+ }
+ }
+ }
+ }
+
+ public static String getName(Field input, Input annotation) {
+ return input.getName();
+ }
+
+ public static String getName(Field config, Config annotation) {
+ return config.getName();
+ }
+
+ public static ConfigurationClass getConfigurationClassAnnotation(Object object, boolean strict) {
+ ConfigurationClass annotation = object.getClass().getAnnotation(ConfigurationClass.class);
+
+ if(strict && annotation == null) {
+ throw new SqoopException(ModelError.MODEL_003, "Missing annotation ConfigurationGroupClass on class " + object.getClass().getName());
+ }
+
+ return annotation;
+ }
+
+ public static ConfigClass getConfigClassAnnotation(Object object, boolean strict) {
+ ConfigClass annotation = object.getClass().getAnnotation(ConfigClass.class);
+
+ if(strict && annotation == null) {
+ throw new SqoopException(ModelError.MODEL_003, "Missing annotation ConfigurationGroupClass on class " + object.getClass().getName());
+ }
+
+ return annotation;
+ }
+
+ public static Config getConfigAnnotation(Field field, boolean strict) {
+ Config annotation = field.getAnnotation(Config.class);
+
+ if(strict && annotation == null) {
+ throw new SqoopException(ModelError.MODEL_003, "Missing annotation Config on Field " + field.getName() + " on class " + field.getDeclaringClass().getName());
+ }
+
+ return annotation;
+ }
+
+ public static Input getInputAnnotation(Field field, boolean strict) {
+ Input annotation = field.getAnnotation(Input.class);
+
+ if(strict && annotation == null) {
+ throw new SqoopException(ModelError.MODEL_003, "Missing annotation Input on Field " + field.getName() + " on class " + field.getDeclaringClass().getName());
+ }
+
+ return annotation;
+ }
+
+ public static Object getFieldValue(Field field, Object object) {
+ try {
+ field.setAccessible(true);
+ return field.get(object);
+ } catch (IllegalAccessException e) {
+ throw new SqoopException(ModelError.MODEL_012, e);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/f63c080d/common/src/main/java/org/apache/sqoop/model/ConfigurationClass.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/model/ConfigurationClass.java b/common/src/main/java/org/apache/sqoop/model/ConfigurationClass.java
index 73374d8..c65c478 100644
--- a/common/src/main/java/org/apache/sqoop/model/ConfigurationClass.java
+++ b/common/src/main/java/org/apache/sqoop/model/ConfigurationClass.java
@@ -23,15 +23,16 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
- * Class annotation. Each class that is used a configuration object where user
- * is expected to provide input need to have this annotation.
+ * Class annotation to represent configuration for the connectors
+ * Each class that is used a configuration group object, the connector developer
+ * is expected to provide the inputs needed for this annotation
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ConfigurationClass {
/**
- * List of validators associated with this Configuration class.
+ * List of validators associated with this Configuration group class.
*
* @return
*/
http://git-wip-us.apache.org/repos/asf/sqoop/blob/f63c080d/common/src/main/java/org/apache/sqoop/model/Form.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/model/Form.java b/common/src/main/java/org/apache/sqoop/model/Form.java
deleted file mode 100644
index 4321582..0000000
--- a/common/src/main/java/org/apache/sqoop/model/Form.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.sqoop.model;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Denote form in Configuration class
- */
-@Retention(RetentionPolicy.RUNTIME)
-public @interface Form {
-}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/f63c080d/common/src/main/java/org/apache/sqoop/model/FormClass.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/model/FormClass.java b/common/src/main/java/org/apache/sqoop/model/FormClass.java
deleted file mode 100644
index 6048d03..0000000
--- a/common/src/main/java/org/apache/sqoop/model/FormClass.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.sqoop.model;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Denote configuration class
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.TYPE)
-public @interface FormClass {
-
- /**
- * Default size for Inputs in this form.
- *
- * @return
- */
- short defaultSize() default -1;
-
- /**
- * List of validators associated with this form.
- *
- * @return
- */
- Validator[] validators() default {};
-}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/f63c080d/common/src/main/java/org/apache/sqoop/model/FormUtils.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/model/FormUtils.java b/common/src/main/java/org/apache/sqoop/model/FormUtils.java
deleted file mode 100644
index ae025ab..0000000
--- a/common/src/main/java/org/apache/sqoop/model/FormUtils.java
+++ /dev/null
@@ -1,565 +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 org.apache.sqoop.utils.ClassUtils;
-import org.apache.sqoop.validation.Message;
-import org.apache.sqoop.validation.Status;
-import org.apache.sqoop.validation.Validation;
-import org.apache.sqoop.validation.ValidationResult;
-import org.json.simple.JSONObject;
-import org.json.simple.JSONValue;
-
-import java.lang.reflect.Field;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Util class for transforming data from correctly annotated configuration
- * objects to different structures and vice-versa.
- *
- * TODO: This class should see some overhaul into more reusable code, especially expose and re-use the methods at the end.
- */
-public class FormUtils {
-
- /**
- * Transform correctly annotated configuration object to corresponding
- * list of forms.
- *
- * Forms will be order according to the occurrence in the configuration
- * class. Inputs will be also ordered based on occurrence.
- *
- * @param configuration Annotated arbitrary configuration object
- * @return Corresponding list of forms
- */
- public static List<MForm> toForms(Object configuration) {
- return toForms(configuration.getClass(), configuration);
- }
-
- public static List<MForm> toForms(Class klass) {
- return toForms(klass, null);
- }
-
- @SuppressWarnings("unchecked")
- public static List<MForm> toForms(Class klass, Object configuration) {
- ConfigurationClass global =
- (ConfigurationClass)klass.getAnnotation(ConfigurationClass.class);
-
- // Each configuration object must have this class annotation
- if(global == null) {
- throw new SqoopException(ModelError.MODEL_003,
- "Missing annotation ConfigurationClass on class " + klass.getName());
- }
-
- List<MForm> forms = new LinkedList<MForm>();
-
- // Iterate over all declared fields
- for (Field field : klass.getDeclaredFields()) {
- field.setAccessible(true);
-
- String formName = field.getName();
-
- // Each field that should be part of user input should have Input
- // annotation.
- Form formAnnotation = field.getAnnotation(Form.class);
-
- if(formAnnotation != null) {
- Class type = field.getType();
-
- Object value = null;
- if(configuration != null) {
- try {
- value = field.get(configuration);
- } catch (IllegalAccessException e) {
- throw new SqoopException(ModelError.MODEL_005,
- "Can't retrieve value from " + field.getName(), e);
- }
- }
-
- forms.add(toForm(formName, type, value));
- }
- }
-
- return forms;
- }
-
- @SuppressWarnings("unchecked")
- private static MForm toForm(String formName, Class klass, Object object) {
- FormClass global =
- (FormClass)klass.getAnnotation(FormClass.class);
-
- // Each configuration object must have this class annotation
- if(global == null) {
- throw new SqoopException(ModelError.MODEL_003,
- "Missing annotation FormClass on class " + klass.getName());
- }
-
- // Intermediate list of inputs
- List<MInput<?>> inputs = new LinkedList<MInput<?>>();
-
- // Iterate over all declared fields
- for (Field field : klass.getDeclaredFields()) {
- field.setAccessible(true);
-
- String fieldName = field.getName();
- String inputName = formName + "." + fieldName;
-
- // Each field that should be part of user input should have Input
- // annotation.
- Input inputAnnotation = field.getAnnotation(Input.class);
-
- if(inputAnnotation != null) {
- boolean sensitive = inputAnnotation.sensitive();
- short maxLen = inputAnnotation.size();
- Class type = field.getType();
-
- MInput input;
-
- // We need to support NULL, so we do not support primitive types
- if(type.isPrimitive()) {
- throw new SqoopException(ModelError.MODEL_007,
- "Detected primitive type " + type + " for field " + fieldName);
- }
-
- // Instantiate corresponding MInput<?> structure
- if(type == String.class) {
- input = new MStringInput(inputName, sensitive, maxLen);
- } else if (type.isAssignableFrom(Map.class)) {
- input = new MMapInput(inputName, sensitive);
- } else if(type == Integer.class) {
- input = new MIntegerInput(inputName, sensitive);
- } else if(type == Boolean.class) {
- input = new MBooleanInput(inputName, sensitive);
- } else if(type.isEnum()) {
- input = new MEnumInput(inputName, sensitive, ClassUtils.getEnumStrings(type));
- } else {
- throw new SqoopException(ModelError.MODEL_004,
- "Unsupported type " + type.getName() + " for input " + fieldName);
- }
-
- // Move value if it's present in original configuration object
- if(object != null) {
- Object value;
- try {
- value = field.get(object);
- } catch (IllegalAccessException e) {
- throw new SqoopException(ModelError.MODEL_005,
- "Can't retrieve value from " + field.getName(), e);
- }
- if(value == null) {
- input.setEmpty();
- } else {
- input.setValue(value);
- }
- }
-
- inputs.add(input);
- }
- }
-
- return new MForm(formName, inputs);
- }
-
- /**
- * Move form values from form list into corresponding configuration object.
- *
- * @param forms Input form list
- * @param configuration Output configuration object
- */
- public static void fromForms(List<MForm> forms, Object configuration) {
- Class klass = configuration.getClass();
-
- for(MForm form : forms) {
- Field formField;
- try {
- formField = klass.getDeclaredField(form.getName());
- } catch (NoSuchFieldException e) {
- throw new SqoopException(ModelError.MODEL_006,
- "Missing field " + form.getName() + " on form class " + klass.getCanonicalName(), e);
- }
-
- // We need to access this field even if it would be declared as private
- formField.setAccessible(true);
-
- Class formClass = formField.getType();
- Object newValue = ClassUtils.instantiate(formClass);
-
- if(newValue == null) {
- throw new SqoopException(ModelError.MODEL_006,
- "Can't instantiate new form " + formClass);
- }
-
- for(MInput input : form.getInputs()) {
- String[] splitNames = input.getName().split("\\.");
- if(splitNames.length != 2) {
- throw new SqoopException(ModelError.MODEL_009,
- "Invalid name: " + input.getName());
- }
-
- String inputName = splitNames[1];
- // TODO(jarcec): Names structures fix, handle error cases
- Field inputField;
- try {
- inputField = formClass.getDeclaredField(inputName);
- } catch (NoSuchFieldException e) {
- throw new SqoopException(ModelError.MODEL_006,
- "Missing field " + input.getName(), e);
- }
-
- // We need to access this field even if it would be declared as private
- inputField.setAccessible(true);
-
- try {
- if(input.isEmpty()) {
- inputField.set(newValue, null);
- } else {
- if (input.getType() == MInputType.ENUM) {
- inputField.set(newValue, Enum.valueOf((Class<? extends Enum>)inputField.getType(), (String) input.getValue()));
- } else {
- inputField.set(newValue, input.getValue());
- }
- }
- } catch (IllegalAccessException e) {
- throw new SqoopException(ModelError.MODEL_005,
- "Issue with field " + inputField.getName(), e);
- }
- }
-
- try {
- formField.set(configuration, newValue);
- } catch (IllegalAccessException e) {
- throw new SqoopException(ModelError.MODEL_005,
- "Issue with field " + formField.getName(), e);
- }
- }
- }
-
- /**
- * Apply validations on the forms.
- *
- * @param forms Forms that should be updated
- * @param validation Validation that we should apply
- */
- public static void applyValidation(List<MForm> forms, Validation validation) {
- Map<Validation.FormInput, Validation.Message> messages = validation.getMessages();
-
- for(MForm form : forms) {
- applyValidation(form, messages);
-
- for(MInput input : form.getInputs()) {
- applyValidation(input, messages);
- }
- }
- }
-
- /**
- * Apply validation on given validated element.
- *
- * @param element Element on what we're applying the validations
- * @param messages Map of all validation messages
- */
- public static void applyValidation(MValidatedElement element, Map<Validation.FormInput, Validation.Message> messages) {
- Validation.FormInput name = new Validation.FormInput(element.getName());
-
- if(messages.containsKey(name)) {
- Validation.Message message = messages.get(name);
- element.addValidationMessage(new Message(message.getStatus(), message.getMessage()));
- } else {
- element.addValidationMessage(new Message(Status.getDefault(), null));
- }
- }
-
-
- /**
- * Apply given validations on list of forms.
- *
- * @param forms
- * @param result
- */
- public static void applyValidation(List<MForm> forms, ValidationResult result) {
- for(MForm form : forms) {
- applyValidation(form, result);
-
- for(MInput input : form.getInputs()) {
- applyValidation(input, result);
- }
- }
- }
-
- /**
- * Apply validation messages on given element.
- *
- * Element's state will be set to default if there are no associated messages.
- *
- * @param element
- * @param result
- */
- public static void applyValidation(MValidatedElement element, ValidationResult result) {
- List<Message> messages = result.getMessages().get(element.getName());
-
- if(messages != null) {
- element.setValidationMessages(messages);
- } else {
- element.resetValidationMessages();
- }
- }
-
- /**
- * Convert configuration object to JSON. Only filled properties are serialized,
- * properties with null value are skipped.
- *
- * @param configuration Correctly annotated configuration object
- * @return String of JSON representation
- */
- @SuppressWarnings("unchecked")
- public static String toJson(Object configuration) {
- Class klass = configuration.getClass();
-
- ConfigurationClass global =
- (ConfigurationClass)klass.getAnnotation(ConfigurationClass.class);
-
- // Each configuration object must have this class annotation
- if(global == null) {
- throw new SqoopException(ModelError.MODEL_003,
- "Missing annotation Configuration on class " + klass.getName());
- }
-
- JSONObject jsonOutput = new JSONObject();
-
- // Iterate over all declared fields
- for (Field formField : klass.getDeclaredFields()) {
- formField.setAccessible(true);
- String formName = formField.getName();
-
- // We're processing only form validations
- Form formAnnotation = formField.getAnnotation(Form.class);
- if(formAnnotation == null) {
- continue;
- }
-
- Object formValue;
- try {
- formValue = formField.get(configuration);
- } catch (IllegalAccessException e) {
- throw new SqoopException(ModelError.MODEL_005,
- "Issue with field " + formName, e);
- }
-
- JSONObject jsonForm = new JSONObject();
-
- // Now process each input on the form
- for(Field inputField : formField.getType().getDeclaredFields()) {
- inputField.setAccessible(true);
- String inputName = inputField.getName();
-
- Object value;
- try {
- value = inputField.get(formValue);
- } catch (IllegalAccessException e) {
- throw new SqoopException(ModelError.MODEL_005,
- "Issue with field " + formName + "." + inputName, e);
- }
-
- Input inputAnnotation = inputField.getAnnotation(Input.class);
-
- // Do not serialize all values
- if(inputAnnotation != null && value != null) {
- Class type = inputField.getType();
-
- // We need to support NULL, so we do not support primitive types
- if(type.isPrimitive()) {
- throw new SqoopException(ModelError.MODEL_007,
- "Detected primitive type " + type + " for field " + formName + "." + inputName);
- }
-
- if(type == String.class) {
- jsonForm.put(inputName, value);
- } else if (type.isAssignableFrom(Map.class)) {
- JSONObject map = new JSONObject();
- for(Object key : ((Map)value).keySet()) {
- map.put(key, ((Map)value).get(key));
- }
- jsonForm.put(inputName, map);
- } else if(type == Integer.class) {
- jsonForm.put(inputName, value);
- } else if(type.isEnum()) {
- jsonForm.put(inputName, value.toString());
- } else if(type == Boolean.class) {
- jsonForm.put(inputName, value);
- }else {
- throw new SqoopException(ModelError.MODEL_004,
- "Unsupported type " + type.getName() + " for input " + formName + "." + inputName);
- }
- }
- }
-
- jsonOutput.put(formName, jsonForm);
- }
-
- return jsonOutput.toJSONString();
- }
-
- /**
- * Parse given input JSON string and move it's values to given configuration
- * object.
- *
- * @param json JSON representation of the configuration object
- * @param configuration Configuration object to be filled
- */
- public static void fillValues(String json, Object configuration) {
- Class klass = configuration.getClass();
-
- JSONObject jsonForms = (JSONObject) JSONValue.parse(json);
-
- for(Field formField : klass.getDeclaredFields()) {
- formField.setAccessible(true);
- String formName = formField.getName();
-
- // We're processing only form validations
- Form formAnnotation = formField.getAnnotation(Form.class);
- if(formAnnotation == null) {
- continue;
- }
-
- try {
- formField.set(configuration, formField.getType().newInstance());
- } catch (Exception e) {
- throw new SqoopException(ModelError.MODEL_005,
- "Issue with field " + formName, e);
- }
-
- JSONObject jsonInputs = (JSONObject) jsonForms.get(formField.getName());
- if(jsonInputs == null) {
- continue;
- }
-
- Object formValue;
- try {
- formValue = formField.get(configuration);
- } catch (IllegalAccessException e) {
- throw new SqoopException(ModelError.MODEL_005,
- "Issue with field " + formName, e);
- }
-
- for(Field inputField : formField.getType().getDeclaredFields()) {
- inputField.setAccessible(true);
- String inputName = inputField.getName();
-
- Input inputAnnotation = inputField.getAnnotation(Input.class);
-
- if(inputAnnotation == null || jsonInputs.get(inputName) == null) {
- try {
- inputField.set(formValue, null);
- } catch (IllegalAccessException e) {
- throw new SqoopException(ModelError.MODEL_005,
- "Issue with field " + formName + "." + inputName, e);
- }
- continue;
- }
-
- Class type = inputField.getType();
-
- try {
- if(type == String.class) {
- inputField.set(formValue, jsonInputs.get(inputName));
- } else if (type.isAssignableFrom(Map.class)) {
- Map<String, String> map = new HashMap<String, String>();
- JSONObject jsonObject = (JSONObject) jsonInputs.get(inputName);
- for(Object key : jsonObject.keySet()) {
- map.put((String)key, (String)jsonObject.get(key));
- }
- inputField.set(formValue, map);
- } else if(type == Integer.class) {
- inputField.set(formValue, ((Long)jsonInputs.get(inputName)).intValue());
- } else if(type.isEnum()) {
- inputField.set(formValue, Enum.valueOf((Class<? extends Enum>) inputField.getType(), (String) jsonInputs.get(inputName)));
- } else if(type == Boolean.class) {
- inputField.set(formValue, (Boolean) jsonInputs.get(inputName));
- }else {
- throw new SqoopException(ModelError.MODEL_004,
- "Unsupported type " + type.getName() + " for input " + formName + "." + inputName);
- }
- } catch (IllegalAccessException e) {
- throw new SqoopException(ModelError.MODEL_005,
- "Issue with field " + formName + "." + inputName, e);
- }
- }
- }
- }
-
- public static String getName(Field input, Input annotation) {
- return input.getName();
- }
-
- public static String getName(Field form, Form annotation) {
- return form.getName();
- }
-
- public static ConfigurationClass getConfigurationClassAnnotation(Object object, boolean strict) {
- ConfigurationClass annotation = object.getClass().getAnnotation(ConfigurationClass.class);
-
- if(strict && annotation == null) {
- throw new SqoopException(ModelError.MODEL_003, "Missing annotation ConfigurationClass on class " + object.getClass().getName());
- }
-
- return annotation;
- }
-
- public static FormClass getFormClassAnnotation(Object object, boolean strict) {
- FormClass annotation = object.getClass().getAnnotation(FormClass.class);
-
- if(strict && annotation == null) {
- throw new SqoopException(ModelError.MODEL_003, "Missing annotation ConfigurationClass on class " + object.getClass().getName());
- }
-
- return annotation;
- }
-
- public static Form getFormAnnotation(Field field, boolean strict) {
- Form annotation = field.getAnnotation(Form.class);
-
- if(strict && annotation == null) {
- throw new SqoopException(ModelError.MODEL_003, "Missing annotation Form on Field " + field.getName() + " on class " + field.getDeclaringClass().getName());
- }
-
- return annotation;
- }
-
- public static Input getInputAnnotation(Field field, boolean strict) {
- Input annotation = field.getAnnotation(Input.class);
-
- if(strict && annotation == null) {
- throw new SqoopException(ModelError.MODEL_003, "Missing annotation Input on Field " + field.getName() + " on class " + field.getDeclaringClass().getName());
- }
-
- return annotation;
- }
-
- public static Object getFieldValue(Field field, Object object) {
- try {
- field.setAccessible(true);
- return field.get(object);
- } catch (IllegalAccessException e) {
- throw new SqoopException(ModelError.MODEL_012, e);
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/f63c080d/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
new file mode 100644
index 0000000..b5d2afd
--- /dev/null
+++ b/common/src/main/java/org/apache/sqoop/model/MConfig.java
@@ -0,0 +1,117 @@
+/**
+ * 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 MConfig extends MValidatedElement implements MClonable {
+
+ private final List<MInput<?>> inputs;
+
+ public MConfig(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("config-").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 MConfig)) {
+ return false;
+ }
+
+ MConfig mf = (MConfig) 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 MConfig clone(boolean cloneWithValue) {
+ List<MInput<?>> copyInputs = new ArrayList<MInput<?>>();
+ for(MInput<?> itr : this.getInputs()) {
+ copyInputs.add((MInput<?>)itr.clone(cloneWithValue));
+ }
+ MConfig copyConfig = new MConfig(this.getName(), copyInputs);
+ return copyConfig;
+ }
+}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/f63c080d/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
new file mode 100644
index 0000000..8747b55
--- /dev/null
+++ b/common/src/main/java/org/apache/sqoop/model/MConfigList.java
@@ -0,0 +1,124 @@
+/**
+ * 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 config objects.
+ */
+public class MConfigList implements MClonable {
+
+ private final List<MConfig> configObjects;
+
+ public MConfigList(List<MConfig> configObjects) {
+ this.configObjects = configObjects;
+ }
+
+ public List<MConfig> getConfigs() {
+ return configObjects;
+ }
+
+ public MConfig getConfig(String configName) {
+ for(MConfig config: configObjects) {
+ if(configName.equals(config.getName())) {
+ return config;
+ }
+ }
+
+ throw new SqoopException(ModelError.MODEL_010, "config name: " + configName);
+ }
+
+ public MInput getInput(String name) {
+ String []parts = name.split("\\.");
+ if(parts.length != 2) {
+ throw new SqoopException(ModelError.MODEL_009, name);
+ }
+
+ return getConfig(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 MConfigList)) return false;
+
+ MConfigList mConfigList = (MConfigList) o;
+
+ if (!configObjects.equals(mConfigList.configObjects)) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = super.hashCode();
+ for(MConfig config : configObjects) {
+ result = 31 * result + config.hashCode();
+ }
+
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("Configs: ");
+ for(MConfig config : configObjects) {
+ sb.append(config.toString());
+ }
+ return sb.toString();
+ }
+
+ @Override
+ public MConfigList clone(boolean cloneWithValue) {
+ List<MConfig> copyConfigs = null;
+ if(this.getConfigs() != null) {
+ copyConfigs = new ArrayList<MConfig>();
+ for(MConfig itr : this.getConfigs()) {
+ MConfig newConfig = itr.clone(cloneWithValue);
+ newConfig.setPersistenceId(itr.getPersistenceId());
+ copyConfigs.add(newConfig);
+ }
+ }
+ MConfigList copyConfigList = new MConfigList(copyConfigs);
+ return copyConfigList;
+ }
+}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/f63c080d/common/src/main/java/org/apache/sqoop/model/MConfigType.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/model/MConfigType.java b/common/src/main/java/org/apache/sqoop/model/MConfigType.java
new file mode 100644
index 0000000..de05332
--- /dev/null
+++ b/common/src/main/java/org/apache/sqoop/model/MConfigType.java
@@ -0,0 +1,34 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sqoop.model;
+
+/**
+ * Represents the various config types supported by the system.
+ */
+public enum MConfigType {
+
+ /** Unknown config type */
+ OTHER,
+
+ /** link config type */
+ LINK,
+
+ /** Job config type */
+ JOB;
+
+}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/f63c080d/common/src/main/java/org/apache/sqoop/model/MConnectionForms.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/model/MConnectionForms.java b/common/src/main/java/org/apache/sqoop/model/MConnectionForms.java
deleted file mode 100644
index 457ccdb..0000000
--- a/common/src/main/java/org/apache/sqoop/model/MConnectionForms.java
+++ /dev/null
@@ -1,54 +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 up an connection
- * object for one part. Both connector and framework need to supply this object
- * to build up entire connection.
- */
-public class MConnectionForms extends MFormList {
-
- public MConnectionForms(List<MForm> forms) {
- super(forms);
- }
-
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder("Connection: ");
- sb.append(super.toString());
- return sb.toString();
- }
-
- @Override
- public boolean equals(Object other) {
- if (other == this) {
- return true;
- }
-
- return super.equals(other);
- }
-
- @Override
- public MConnectionForms clone(boolean cloneWithValue) {
- MConnectionForms copy = new MConnectionForms(super.clone(cloneWithValue).getForms());
- return copy;
- }
-}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/f63c080d/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/f63c080d/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