sqoop-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From b...@apache.org
Subject [2/3] SQOOP-596: Implement connection resource end-to-end
Date Fri, 07 Sep 2012 19:48:36 GMT
http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/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
new file mode 100644
index 0000000..dc4aac3
--- /dev/null
+++ b/common/src/main/java/org/apache/sqoop/json/util/ResourceBundleSerialization.java
@@ -0,0 +1,83 @@
+/**
+ * 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.sqoop.utils.MapResourceBundle;
+import org.json.simple.JSONArray;
+import org.json.simple.JSONObject;
+
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.ResourceBundle;
+
+/**
+ *
+ */
+public class ResourceBundleSerialization {
+
+  public static final String RESOURCES = "resources";
+  public static final String CONNECTOR_RESOURCES = "resources-connector";
+  public static final String FRAMEWORK_RESOURCES = "resources-framework";
+
+  @SuppressWarnings("unchecked")
+  public static JSONArray extractResourceBundles(List<ResourceBundle> bundles) {
+    JSONArray array = new JSONArray();
+    for (ResourceBundle bundle : bundles) {
+      array.add(extractResourceBundle(bundle));
+    }
+
+    return array;
+  }
+
+  @SuppressWarnings("unchecked")
+  public static JSONObject extractResourceBundle(ResourceBundle bundle) {
+    JSONObject json = new JSONObject();
+
+    Enumeration<String> keys = bundle.getKeys();
+
+    while(keys.hasMoreElements()) {
+      String key = keys.nextElement();
+
+      json.put(key, bundle.getString(key));
+
+    }
+
+    return json;
+  }
+
+  @SuppressWarnings("unchecked")
+  public static List<ResourceBundle> restoreResourceBundles(JSONArray array) {
+    List<ResourceBundle> bundles = new LinkedList<ResourceBundle>();
+
+    for (Object item : array) {
+      bundles.add(restoreResourceBundle((JSONObject) item));
+    }
+
+    return bundles;
+  }
+
+  @SuppressWarnings("unchecked")
+  public static ResourceBundle restoreResourceBundle(JSONObject json) {
+    Map<String, Object> map = new HashMap<String, Object>();
+    map.putAll(json);
+    return new MapResourceBundle(map);
+  }
+}

http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/common/src/main/java/org/apache/sqoop/model/MConnection.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/model/MConnection.java b/common/src/main/java/org/apache/sqoop/model/MConnection.java
index ad5f48f..97771a3 100644
--- a/common/src/main/java/org/apache/sqoop/model/MConnection.java
+++ b/common/src/main/java/org/apache/sqoop/model/MConnection.java
@@ -21,20 +21,47 @@ package org.apache.sqoop.model;
  * Model describing entire connection object including both connector and
  * framework part.
  */
-public class MConnection extends MNamedElement {
-  // TODO(jarcec): We probably need reference to connector object here
+public class MConnection extends MPersistableEntity {
+  long connectorId;
+  String name;
+
   MConnectionForms connectorPart;
   MConnectionForms frameworkPart;
 
-  public MConnection(String name) {
-    super(name);
+  public MConnection(long connectorId,
+                     MConnectionForms connectorPart,
+                     MConnectionForms frameworkPart) {
+    this.connectorId = connectorId;
+    this.connectorPart = connectorPart;
+    this.frameworkPart = frameworkPart;
   }
 
   @Override
   public String toString() {
-    StringBuilder sb = new StringBuilder("connection connector-part: ");
-    sb.append(connectorPart).append(", framework-part: ").append(frameworkPart);
+    StringBuilder sb = new StringBuilder("connection: ").append(name);
+    sb.append(" connector-part: ").append(connectorPart);
+    sb.append(", framework-part: ").append(frameworkPart);
 
     return sb.toString();
   }
+
+  public String getName() {
+    return name;
+  }
+
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  public long getConnectorId() {
+    return connectorId;
+  }
+
+  public MConnectionForms getConnectorPart() {
+    return connectorPart;
+  }
+
+  public MConnectionForms getFrameworkPart() {
+    return frameworkPart;
+  }
 }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/common/src/main/java/org/apache/sqoop/model/MInput.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/model/MInput.java b/common/src/main/java/org/apache/sqoop/model/MInput.java
index ec7cc2b..2a87531 100644
--- a/common/src/main/java/org/apache/sqoop/model/MInput.java
+++ b/common/src/main/java/org/apache/sqoop/model/MInput.java
@@ -88,6 +88,21 @@ public abstract class MInput<T> extends MValidatedElement {
   @Override
   public abstract int hashCode();
 
+  /**
+   * All input types must be able to tell if they contain some value or not.
+   *
+   * Empty values won't be serialized into metadata repository and will not be
+   * send across the wire between client and server.
+   *
+   * @return True if this input contains empty value.
+   */
+  public abstract boolean isEmpty();
+
+  /**
+   * Set Input value to empty value.
+   */
+  public abstract void setEmpty();
+
   @Override
   public final String toString() {
     StringBuilder sb = new StringBuilder("input-").append(getName());

http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/common/src/main/java/org/apache/sqoop/model/MMapInput.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/model/MMapInput.java b/common/src/main/java/org/apache/sqoop/model/MMapInput.java
index 528f667..9818d71 100644
--- a/common/src/main/java/org/apache/sqoop/model/MMapInput.java
+++ b/common/src/main/java/org/apache/sqoop/model/MMapInput.java
@@ -104,4 +104,14 @@ public final class MMapInput extends MInput<Map<String, String>> {
   public int hashCode() {
     return 23 + 31 * getName().hashCode();
   }
+
+  @Override
+  public boolean isEmpty() {
+    return getValue() == null;
+  }
+
+  @Override
+  public void setEmpty() {
+    setValue(null);
+  }
 }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/common/src/main/java/org/apache/sqoop/model/MStringInput.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/model/MStringInput.java b/common/src/main/java/org/apache/sqoop/model/MStringInput.java
index 7f20803..04afb38 100644
--- a/common/src/main/java/org/apache/sqoop/model/MStringInput.java
+++ b/common/src/main/java/org/apache/sqoop/model/MStringInput.java
@@ -104,4 +104,14 @@ public final class MStringInput extends MInput<String> {
     result = 31 * result + maxLength;
     return result;
   }
+
+  @Override
+  public boolean isEmpty() {
+    return getValue() == null;
+  }
+
+  @Override
+  public void setEmpty() {
+    setValue(null);
+  }
 }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/common/src/main/java/org/apache/sqoop/utils/MapResourceBundle.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/utils/MapResourceBundle.java b/common/src/main/java/org/apache/sqoop/utils/MapResourceBundle.java
new file mode 100644
index 0000000..b0a15e7
--- /dev/null
+++ b/common/src/main/java/org/apache/sqoop/utils/MapResourceBundle.java
@@ -0,0 +1,49 @@
+/**
+ * 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.utils;
+
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Map;
+import java.util.ResourceBundle;
+
+/**
+ *
+ */
+public class MapResourceBundle extends ResourceBundle {
+
+  private Map<String, Object> bundle;
+
+  public MapResourceBundle(Map<String, Object> bundle) {
+    this.bundle = bundle;
+  }
+
+  @Override
+  protected Object handleGetObject(String key) {
+    if(!bundle.containsKey(key)) {
+      return null;
+    }
+
+    return bundle.get(key);
+  }
+
+  @Override
+  public Enumeration<String> getKeys() {
+    return Collections.enumeration(bundle.keySet());
+  }
+}

http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/common/src/main/java/org/apache/sqoop/validation/Status.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/validation/Status.java b/common/src/main/java/org/apache/sqoop/validation/Status.java
new file mode 100644
index 0000000..5c9fb9c
--- /dev/null
+++ b/common/src/main/java/org/apache/sqoop/validation/Status.java
@@ -0,0 +1,69 @@
+/**
+ * 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;
+
+/**
+ * Status modes of a validation process.
+ */
+public enum Status {
+  /**
+   * There are no issues, no warnings. Everything is correct.
+   */
+  FINE,
+
+  /**
+   * Validated entity is correct enough to be processed. There might be some
+   * warnings, but no errors.
+   */
+  ACCEPTABLE,
+
+  /**
+   * There are serious issues with validated entity. We can't proceed until
+   * reported issues will be resolved.
+   */
+  UNACCEPTABLE,
+
+  ;
+
+  /**
+   * Compare multiple statuses and return the worst one.
+   *
+   * @param statuses Multiple statuses
+   * @return The worst status
+   */
+  public static Status getWorstStatus(Status ... statuses) {
+    Status finalStatus = FINE;
+
+    for (Status status : statuses) {
+      if (finalStatus.compareTo(status) < 1) {
+        finalStatus = status;
+      }
+    }
+
+    return finalStatus;
+  }
+
+  /**
+   * Find out if this status object is good enough to proceed.
+   *
+   * @return True if we can proceed with processing
+   */
+  public boolean canProceed() {
+    return this == FINE || this == ACCEPTABLE;
+  }
+}

http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/common/src/test/java/org/apache/sqoop/json/TestConnectionBean.java
----------------------------------------------------------------------
diff --git a/common/src/test/java/org/apache/sqoop/json/TestConnectionBean.java b/common/src/test/java/org/apache/sqoop/json/TestConnectionBean.java
new file mode 100644
index 0000000..c11b600
--- /dev/null
+++ b/common/src/test/java/org/apache/sqoop/json/TestConnectionBean.java
@@ -0,0 +1,66 @@
+/**
+ * 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;
+
+import org.apache.sqoop.model.MConnection;
+import org.apache.sqoop.model.MStringInput;
+import org.json.simple.JSONObject;
+import org.json.simple.JSONValue;
+import org.junit.Test;
+
+import static junit.framework.Assert.*;
+import static org.apache.sqoop.json.TestUtil.*;
+
+/**
+ *
+ */
+public class TestConnectionBean {
+  @Test
+  public void testSerialization() {
+    MConnection connection = getConnection("ahoj");
+    connection.setName("Connection");
+    connection.setPersistenceId(666);
+
+    // Fill some data at the beginning
+    MStringInput input = (MStringInput) connection.getConnectorPart().getForms()
+      .get(0).getInputs().get(0);
+    input.setValue("Hi there!");
+
+    // Serialize it to JSON object
+    ConnectionBean bean = new ConnectionBean(connection);
+    JSONObject json = bean.extract();
+
+    // "Move" it across network in text form
+    String string = json.toJSONString();
+
+    // Retrieved transferred object
+    JSONObject retrievedJson = (JSONObject) JSONValue.parse(string);
+    ConnectionBean retrievedBean = new ConnectionBean();
+    retrievedBean.restore(retrievedJson);
+    MConnection target = retrievedBean.getConnections().get(0);
+
+    // Check id and name
+    assertEquals(666, target.getPersistenceId());
+    assertEquals("Connection", target.getName());
+
+    // Test that value was correctly moved
+    MStringInput targetInput = (MStringInput) target.getConnectorPart()
+      .getForms().get(0).getInputs().get(0);
+    assertEquals("Hi there!", targetInput.getValue());
+  }
+}

http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/common/src/test/java/org/apache/sqoop/json/TestConnectorBean.java
----------------------------------------------------------------------
diff --git a/common/src/test/java/org/apache/sqoop/json/TestConnectorBean.java b/common/src/test/java/org/apache/sqoop/json/TestConnectorBean.java
index 0dd13ed..dc8dd95 100644
--- a/common/src/test/java/org/apache/sqoop/json/TestConnectorBean.java
+++ b/common/src/test/java/org/apache/sqoop/json/TestConnectorBean.java
@@ -19,20 +19,16 @@ package org.apache.sqoop.json;
 
 import static org.junit.Assert.*;
 
-import org.apache.sqoop.model.MConnectionForms;
-import org.apache.sqoop.model.MJob;
 import org.apache.sqoop.model.MConnector;
-import org.apache.sqoop.model.MForm;
-import org.apache.sqoop.model.MInput;
-import org.apache.sqoop.model.MJobForms;
-import org.apache.sqoop.model.MMapInput;
-import org.apache.sqoop.model.MStringInput;
 import org.json.simple.JSONObject;
 import org.json.simple.JSONValue;
 import org.junit.Test;
 
-import java.util.ArrayList;
+import java.util.LinkedList;
 import java.util.List;
+import java.util.ResourceBundle;
+
+import static org.apache.sqoop.json.TestUtil.*;
 
 /**
  *
@@ -46,12 +42,17 @@ public class TestConnectorBean {
   @Test
   public void testSerialization() {
     // Create testing connector
-    MConnector[] connectors = new MConnector[2];
-    connectors[0] = buildFakeConnector("jdbc");
-    connectors[1] = buildFakeConnector("mysql");
+    List<MConnector> connectors = new LinkedList<MConnector>();
+    connectors.add(getConnector("jdbc"));
+    connectors.add(getConnector("mysql"));
+
+    // Create testing bundles
+    List<ResourceBundle> bundles = new LinkedList<ResourceBundle>();
+    bundles.add(getResourceBundle());
+    bundles.add(getResourceBundle());
 
     // Serialize it to JSON object
-    ConnectorBean bean = new ConnectorBean(connectors);
+    ConnectorBean bean = new ConnectorBean(connectors, bundles);
     JSONObject json = bean.extract();
 
     // "Move" it across network in text form
@@ -62,41 +63,11 @@ public class TestConnectorBean {
     ConnectorBean retrievedBean = new ConnectorBean();
     retrievedBean.restore(retrievedJson);
 
-    assertEquals(connectors.length, retrievedBean.getConnectors().length);
-    assertEquals(connectors[0], retrievedBean.getConnectors()[0]);
-  }
-
-  protected MConnector buildFakeConnector(String name) {
-    List<MInput<?>> inputs;
-
-    List<MForm> connectionForms = new ArrayList<MForm>();
-    inputs = new ArrayList<MInput<?>>();
-    inputs.add(new MStringInput("url", false, (short) 10));
-    inputs.add(new MStringInput("username", false, (short) 10));
-    inputs.add(new MStringInput("password", false, (short) 10));
-    connectionForms.add(new MForm("connection", inputs));
-
-    inputs = new ArrayList<MInput<?>>();
-    inputs.add(new MMapInput("properties"));
-    connectionForms.add(new MForm("properties", inputs));
-    MConnectionForms connection = new MConnectionForms(connectionForms);
-
-    List<MForm> jobForms = new ArrayList<MForm>();
-    inputs = new ArrayList<MInput<?>>();
-    inputs.add(new MStringInput("A", false, (short) 10));
-    inputs.add(new MStringInput("B", false, (short) 10));
-    inputs.add(new MStringInput("C", false, (short) 10));
-    jobForms.add((new MForm("D", inputs)));
-
-    inputs = new ArrayList<MInput<?>>();
-    inputs.add(new MStringInput("Z", false, (short) 10));
-    inputs.add(new MStringInput("X", false, (short) 10));
-    inputs.add(new MStringInput("Y", false, (short) 10));
-    jobForms.add(new MForm("D", inputs));
-
-    List<MJobForms> jobs = new ArrayList<MJobForms>();
-    jobs.add(new MJobForms(MJob.Type.IMPORT, jobForms));
+    assertEquals(connectors.size(), retrievedBean.getConnectors().size());
+    assertEquals(connectors.get(0), retrievedBean.getConnectors().get(0));
 
-    return new MConnector(name, name + ".class", connection, jobs);
+    ResourceBundle retrievedBundle = retrievedBean.getResourceBundles().get(0);
+    assertEquals("a", retrievedBundle.getString("a"));
+    assertEquals("b", retrievedBundle.getString("b"));
   }
 }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/common/src/test/java/org/apache/sqoop/json/TestFrameworkBean.java
----------------------------------------------------------------------
diff --git a/common/src/test/java/org/apache/sqoop/json/TestFrameworkBean.java b/common/src/test/java/org/apache/sqoop/json/TestFrameworkBean.java
index 50044d9..5aa581b 100644
--- a/common/src/test/java/org/apache/sqoop/json/TestFrameworkBean.java
+++ b/common/src/test/java/org/apache/sqoop/json/TestFrameworkBean.java
@@ -17,20 +17,15 @@
  */
 package org.apache.sqoop.json;
 
-import org.apache.sqoop.model.MConnectionForms;
-import org.apache.sqoop.model.MForm;
 import org.apache.sqoop.model.MFramework;
-import org.apache.sqoop.model.MInput;
-import org.apache.sqoop.model.MJob;
-import org.apache.sqoop.model.MJobForms;
-import org.apache.sqoop.model.MMapInput;
-import org.apache.sqoop.model.MStringInput;
 import org.json.simple.JSONObject;
 import org.json.simple.JSONValue;
 import org.junit.Test;
 
-import java.util.ArrayList;
-import java.util.List;
+import java.util.ResourceBundle;
+
+import static org.apache.sqoop.json.TestUtil.*;
+
 
 import static org.junit.Assert.*;
 
@@ -45,9 +40,10 @@ public class TestFrameworkBean {
    */
   @Test
   public void testSerialization() {
-    MFramework framework = getFramework("1");
+    MFramework framework = getFramework();
+
     // Serialize it to JSON object
-    FrameworkBean bean = new FrameworkBean(framework);
+    FrameworkBean bean = new FrameworkBean(framework, getResourceBundle());
     JSONObject json = bean.extract();
 
     // "Move" it across network in text form
@@ -59,40 +55,10 @@ public class TestFrameworkBean {
     retrievedBean.restore(retrievedJson);
 
     assertEquals(framework, retrievedBean.getFramework());
-  }
-
-  public MFramework getFramework(String parameter) {
-    List<MInput<?>> inputs;
-
-    List<MForm> connectionForms = new ArrayList<MForm>();
-    inputs = new ArrayList<MInput<?>>();
-    inputs.add(new MStringInput("url", false, (short) 10));
-    inputs.add(new MStringInput("username", false, (short) 10));
-    inputs.add(new MStringInput("password", false, (short) 10));
-    connectionForms.add(new MForm("connection", inputs));
-
-    inputs = new ArrayList<MInput<?>>();
-    inputs.add(new MMapInput("properties"));
-    connectionForms.add(new MForm("properties", inputs));
-    MConnectionForms connection = new MConnectionForms(connectionForms);
-
-    List<MForm> jobForms = new ArrayList<MForm>();
-    inputs = new ArrayList<MInput<?>>();
-    inputs.add(new MStringInput("A", false, (short) 10));
-    inputs.add(new MStringInput("B", false, (short) 10));
-    inputs.add(new MStringInput("C", false, (short) 10));
-    jobForms.add((new MForm("D", inputs)));
-
-    inputs = new ArrayList<MInput<?>>();
-    inputs.add(new MStringInput("Z", false, (short) 10));
-    inputs.add(new MStringInput("X", false, (short) 10));
-    inputs.add(new MStringInput("Y", false, (short) 10));
-    jobForms.add(new MForm("D", inputs));
-
-    List<MJobForms> jobs = new ArrayList<MJobForms>();
-    jobs.add(new MJobForms(MJob.Type.IMPORT, jobForms));
 
-    return new MFramework(connection, jobs);
+    ResourceBundle retrievedBundle = retrievedBean.getResourceBundle();
+    assertEquals("a", retrievedBundle.getString("a"));
+    assertEquals("b", retrievedBundle.getString("b"));
   }
 
 }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/common/src/test/java/org/apache/sqoop/json/TestUtil.java
----------------------------------------------------------------------
diff --git a/common/src/test/java/org/apache/sqoop/json/TestUtil.java b/common/src/test/java/org/apache/sqoop/json/TestUtil.java
new file mode 100644
index 0000000..57bfa91
--- /dev/null
+++ b/common/src/test/java/org/apache/sqoop/json/TestUtil.java
@@ -0,0 +1,137 @@
+/**
+ * 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;
+
+import org.apache.sqoop.model.MConnection;
+import org.apache.sqoop.model.MConnectionForms;
+import org.apache.sqoop.model.MConnector;
+import org.apache.sqoop.model.MForm;
+import org.apache.sqoop.model.MFramework;
+import org.apache.sqoop.model.MInput;
+import org.apache.sqoop.model.MJob;
+import org.apache.sqoop.model.MJobForms;
+import org.apache.sqoop.model.MStringInput;
+import org.apache.sqoop.utils.MapResourceBundle;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.ResourceBundle;
+
+/**
+ *
+ */
+public class TestUtil {
+  public static MConnector getConnector(String name) {
+    return new MConnector(name, name + ".class",
+      getConnectionForms(), getAllJobForms());
+  }
+
+  public static MFramework getFramework() {
+    return new MFramework(getConnectionForms(), getAllJobForms());
+  }
+
+  public static MConnection getConnection(String name) {
+    return new MConnection(1,
+                           getConnector(name).getConnectionForms(),
+                           getFramework().getConnectionForms());
+  }
+
+  public static MConnectionForms getConnectionForms() {
+    List<MInput<?>> inputs;
+    MStringInput input;
+    MForm form;
+    List<MForm> connectionForms = new ArrayList<MForm>();
+    inputs = new ArrayList<MInput<?>>();
+
+    input = new MStringInput("url", false, (short) 10);
+    input.setPersistenceId(1);
+    inputs.add(input);
+
+    input = new MStringInput("username", false, (short) 10);
+    input.setPersistenceId(2);
+    inputs.add(input);
+
+    input = new MStringInput("password", false, (short) 10);
+    input.setPersistenceId(3);
+    inputs.add(input);
+
+    form = new MForm("connection", inputs);
+    form.setPersistenceId(10);
+    connectionForms.add(form);
+
+    return new MConnectionForms(connectionForms);
+  }
+
+  public static List<MJobForms> getAllJobForms() {
+    List<MInput<?>> inputs;
+    MStringInput input;
+    MForm form;
+    List<MForm> jobForms = new ArrayList<MForm>();
+
+    inputs = new ArrayList<MInput<?>>();
+
+    input = new MStringInput("A", false, (short) 10);
+    input.setPersistenceId(4);
+    inputs.add(input);
+
+    input = new MStringInput("B", false, (short) 10);
+    input.setPersistenceId(5);
+    inputs.add(input);
+
+    input = new MStringInput("C", false, (short) 10);
+    input.setPersistenceId(6);
+    inputs.add(input);
+
+    form = new MForm("Z", inputs);
+    form.setPersistenceId(11);
+    jobForms.add(form);
+
+    inputs = new ArrayList<MInput<?>>();
+
+    input = new MStringInput("D", false, (short) 10);
+    input.setPersistenceId(7);
+    inputs.add(input);
+
+    input = new MStringInput("E", false, (short) 10);
+    input.setPersistenceId(8);
+    inputs.add(input);
+
+    input = new MStringInput("F", false, (short) 10);
+    input.setPersistenceId(9);
+    inputs.add(input);
+
+    form = new MForm("connection", inputs);
+    form.setPersistenceId(12);
+    jobForms.add(form);
+
+    List<MJobForms> jobs = new ArrayList<MJobForms>();
+    jobs.add(new MJobForms(MJob.Type.IMPORT, jobForms));
+
+    return jobs;
+  }
+
+  public static ResourceBundle getResourceBundle() {
+    Map<String, Object> map = new HashMap<String, Object>();
+    map.put("a", "a");
+    map.put("b", "b");
+
+    return new MapResourceBundle(map);
+  }
+}

http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/common/src/test/java/org/apache/sqoop/json/TestValidationBean.java
----------------------------------------------------------------------
diff --git a/common/src/test/java/org/apache/sqoop/json/TestValidationBean.java b/common/src/test/java/org/apache/sqoop/json/TestValidationBean.java
new file mode 100644
index 0000000..738b4e5
--- /dev/null
+++ b/common/src/test/java/org/apache/sqoop/json/TestValidationBean.java
@@ -0,0 +1,69 @@
+/**
+ * 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;
+
+import org.apache.sqoop.model.MConnection;
+import org.apache.sqoop.model.MStringInput;
+import org.apache.sqoop.model.MValidatedElement;
+import org.apache.sqoop.validation.Status;
+import org.json.simple.JSONObject;
+import org.json.simple.JSONValue;
+import org.junit.Test;
+
+import static org.apache.sqoop.json.TestUtil.getConnection;
+import static org.junit.Assert.*;
+
+/**
+ *
+ */
+public class TestValidationBean {
+
+  private static final String CONNECTOR_NAME = "coolest-connector";
+  private static final String ERROR_MESSAGE = "Houston, we have a problem!";
+
+  @Test
+  public void testSerialization() {
+    MConnection connection = getConnection(CONNECTOR_NAME);
+    MConnection target = getConnection(CONNECTOR_NAME);
+
+    // Fill some data at the beginning
+    MStringInput input = (MStringInput) connection.getConnectorPart().getForms()
+      .get(0).getInputs().get(0);
+    input.setErrorMessage(ERROR_MESSAGE);
+
+    // Serialize it to JSON object
+    ValidationBean bean = new ValidationBean(connection, Status.UNACCEPTABLE);
+    JSONObject json = bean.extract();
+
+    // "Move" it across network in text form
+    String string = json.toJSONString();
+
+    // Retrieved transferred object
+    JSONObject retrievedJson = (JSONObject) JSONValue.parse(string);
+    ValidationBean retrievedBean = new ValidationBean(target);
+    retrievedBean.restore(retrievedJson);
+
+    // Test that value had been correctly moved
+    MStringInput targetInput = (MStringInput) target.getConnectorPart()
+      .getForms().get(0).getInputs().get(0);
+    assertEquals(MValidatedElement.Severity.ERROR,
+      targetInput.getValidationSeverity());
+    assertEquals(ERROR_MESSAGE,
+      targetInput.getValidationMessage());
+  }
+}

http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/common/src/test/java/org/apache/sqoop/utils/TestMapResourceBundle.java
----------------------------------------------------------------------
diff --git a/common/src/test/java/org/apache/sqoop/utils/TestMapResourceBundle.java b/common/src/test/java/org/apache/sqoop/utils/TestMapResourceBundle.java
new file mode 100644
index 0000000..1edc404
--- /dev/null
+++ b/common/src/test/java/org/apache/sqoop/utils/TestMapResourceBundle.java
@@ -0,0 +1,41 @@
+/**
+ * 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.utils;
+
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.Assert.*;
+
+/**
+ *
+ */
+public class TestMapResourceBundle {
+  @Test
+  public void testUsage() {
+    Map<String, Object> map = new HashMap<String, Object>();
+    map.put("a", "1");
+    map.put("b", "2");
+
+    MapResourceBundle bundle = new MapResourceBundle(map);
+    assertEquals("1", bundle.getString("a"));
+    assertEquals("2", bundle.getString("b"));
+  }
+}

http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/common/src/test/java/org/apache/sqoop/validation/TestStatus.java
----------------------------------------------------------------------
diff --git a/common/src/test/java/org/apache/sqoop/validation/TestStatus.java b/common/src/test/java/org/apache/sqoop/validation/TestStatus.java
new file mode 100644
index 0000000..5b17a4e
--- /dev/null
+++ b/common/src/test/java/org/apache/sqoop/validation/TestStatus.java
@@ -0,0 +1,53 @@
+/**
+ * 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.junit.Test;
+
+import static junit.framework.Assert.*;
+
+/**
+ *
+ */
+public class TestStatus {
+  @Test
+  public void testGetWorstStatus() {
+    // Comparing itself with itself
+    assertEquals(Status.FINE,
+      Status.getWorstStatus(Status.FINE));
+    assertEquals(Status.FINE,
+      Status.getWorstStatus(Status.FINE, Status.FINE));
+    assertEquals(Status.ACCEPTABLE,
+      Status.getWorstStatus(Status.ACCEPTABLE, Status.ACCEPTABLE));
+    assertEquals(Status.UNACCEPTABLE,
+      Status.getWorstStatus(Status.UNACCEPTABLE, Status.UNACCEPTABLE));
+
+    // Retriving the worst option
+    assertEquals(Status.UNACCEPTABLE,
+      Status.getWorstStatus(Status.FINE, Status.UNACCEPTABLE));
+    assertEquals(Status.ACCEPTABLE,
+      Status.getWorstStatus(Status.FINE, Status.ACCEPTABLE));
+  }
+
+  @Test
+  public void testCanProceed() {
+    assertTrue(Status.FINE.canProceed());
+    assertTrue(Status.ACCEPTABLE.canProceed());
+    assertFalse(Status.UNACCEPTABLE.canProceed());
+  }
+}

http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/GenericJdbcConnector.java
----------------------------------------------------------------------
diff --git a/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/GenericJdbcConnector.java b/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/GenericJdbcConnector.java
index 1655da9..4363e0a 100644
--- a/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/GenericJdbcConnector.java
+++ b/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/GenericJdbcConnector.java
@@ -122,7 +122,8 @@ public class GenericJdbcConnector implements SqoopConnector {
 
   @Override
   public Validator getValidator() {
-    return new Validator();
+    // TODO(jarcec): Cache this object eventually
+    return new GenericJdbcValidator();
   }
 
 }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/GenericJdbcConnectorConstants.java
----------------------------------------------------------------------
diff --git a/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/GenericJdbcConnectorConstants.java b/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/GenericJdbcConnectorConstants.java
index 7e46ac7..0e45241 100644
--- a/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/GenericJdbcConnectorConstants.java
+++ b/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/GenericJdbcConnectorConstants.java
@@ -26,7 +26,6 @@ public final class GenericJdbcConnectorConstants {
   public static final String RESOURCE_BUNDLE_NAME =
       "generic-jdbc-connector-resources";
 
-
   // Metadata constants
 
   // Connection form
@@ -41,7 +40,7 @@ public final class GenericJdbcConnectorConstants {
   public static final String INPUT_CONN_JDBCPROPS = "inp-conn-jdbc-properties";
 
   // Table form
-  public static final String FORM_TABLE = "table-connection";
+  public static final String FORM_TABLE = "form-table";
 
   // Table form inputs
   public static final String INPUT_TBL_TABLE = "inp-tbl-table";

http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/GenericJdbcValidator.java
----------------------------------------------------------------------
diff --git a/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/GenericJdbcValidator.java b/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/GenericJdbcValidator.java
new file mode 100644
index 0000000..d307aff
--- /dev/null
+++ b/connector/connector-generic-jdbc/src/main/java/org/apache/sqoop/connector/jdbc/GenericJdbcValidator.java
@@ -0,0 +1,63 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sqoop.connector.jdbc;
+
+import org.apache.sqoop.model.MForm;
+import org.apache.sqoop.model.MInput;
+import org.apache.sqoop.validation.Status;
+import org.apache.sqoop.validation.Validator;
+
+import java.util.List;
+
+import static org.apache.sqoop.connector.jdbc.GenericJdbcConnectorConstants.*;
+
+/**
+ *
+ */
+public class GenericJdbcValidator extends Validator {
+
+  @Override
+  public Status validate(MForm form) {
+    if (form.getName().equals(FORM_CONNECTION)) {
+      return validateConnectionForm(form);
+    }
+
+    // This do not seem as our form
+    return Status.UNACCEPTABLE;
+  }
+
+  private Status validateConnectionForm(MForm form) {
+    Status status = Status.FINE;
+
+    List<MInput<?>> inputs = form.getInputs();
+
+    for (MInput input : inputs) {
+      // JDBC connection string must start with "jdbc:"
+      if (input.getName().equals(INPUT_CONN_CONNECTSTRING)) {
+        String jdbcUrl = (String) input.getValue();
+
+        if(jdbcUrl == null || !jdbcUrl.startsWith("jdbc:")) {
+          status = Status.UNACCEPTABLE;
+          input.setErrorMessage("This do not seem as a valid JDBC URL.");
+        }
+      }
+    }
+
+    return status;
+  }
+}

http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/connector/connector-generic-jdbc/src/main/resources/generic-jdbc-connector-resources.properties
----------------------------------------------------------------------
diff --git a/connector/connector-generic-jdbc/src/main/resources/generic-jdbc-connector-resources.properties b/connector/connector-generic-jdbc/src/main/resources/generic-jdbc-connector-resources.properties
index 10be0e8..c589339 100644
--- a/connector/connector-generic-jdbc/src/main/resources/generic-jdbc-connector-resources.properties
+++ b/connector/connector-generic-jdbc/src/main/resources/generic-jdbc-connector-resources.properties
@@ -18,8 +18,7 @@
 ############################
 # Connection Form
 #
-form-connection-label = Please provide the following information to create a \
-                   connection:
+form-connection-label = Configuration configuration
 form-connection-help = You must supply the information requested in order to \
                    create a connection object.
 
@@ -48,5 +47,12 @@ inp-conn-jdbc-properties-label = JDBC Connection Properties
 inp-conn-jdbc-properties-help = Enter any JDBC properties that should be \
                    supplied during the creation of connection.
 
+# Table From
+#
+form-table-label = Database configuration
+form-table-help = You must supply the information requested in order to create \
+                  a connection object.
 
-
+# Table name
+inp-tbl-table-label = Table name
+inp-tbl-table-help = Name of the table in remote database

http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/connector/connector-mysql-jdbc/src/main/java/org/apache/sqoop/connector/mysqljdbc/MySqlJdbcConnector.java
----------------------------------------------------------------------
diff --git a/connector/connector-mysql-jdbc/src/main/java/org/apache/sqoop/connector/mysqljdbc/MySqlJdbcConnector.java b/connector/connector-mysql-jdbc/src/main/java/org/apache/sqoop/connector/mysqljdbc/MySqlJdbcConnector.java
index aa22fcc..17215f0 100644
--- a/connector/connector-mysql-jdbc/src/main/java/org/apache/sqoop/connector/mysqljdbc/MySqlJdbcConnector.java
+++ b/connector/connector-mysql-jdbc/src/main/java/org/apache/sqoop/connector/mysqljdbc/MySqlJdbcConnector.java
@@ -18,6 +18,7 @@
 package org.apache.sqoop.connector.mysqljdbc;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
 import java.util.ResourceBundle;
@@ -28,6 +29,7 @@ import org.apache.sqoop.model.MConnectionForms;
 import org.apache.sqoop.model.MForm;
 import org.apache.sqoop.connector.spi.SqoopConnector;
 import org.apache.sqoop.model.MJobForms;
+import org.apache.sqoop.utils.MapResourceBundle;
 import org.apache.sqoop.validation.Validator;
 
 public class MySqlJdbcConnector implements SqoopConnector {
@@ -37,8 +39,7 @@ public class MySqlJdbcConnector implements SqoopConnector {
 
   @Override
   public ResourceBundle getBundle(Locale locale) {
-    // TODO Auto-generated method stub
-    return null;
+    return new MapResourceBundle(new HashMap<String, Object>());
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/core/src/main/java/org/apache/sqoop/connector/ConnectorHandler.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/sqoop/connector/ConnectorHandler.java b/core/src/main/java/org/apache/sqoop/connector/ConnectorHandler.java
index 2798aff..8014be1 100644
--- a/core/src/main/java/org/apache/sqoop/connector/ConnectorHandler.java
+++ b/core/src/main/java/org/apache/sqoop/connector/ConnectorHandler.java
@@ -115,4 +115,8 @@ public final class ConnectorHandler {
   public MConnector getMetadata() {
     return mConnector;
   }
+
+  public SqoopConnector getConnector() {
+    return connector;
+  }
 }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/core/src/main/java/org/apache/sqoop/connector/ConnectorManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/sqoop/connector/ConnectorManager.java b/core/src/main/java/org/apache/sqoop/connector/ConnectorManager.java
index c47752c..ea368da 100644
--- a/core/src/main/java/org/apache/sqoop/connector/ConnectorManager.java
+++ b/core/src/main/java/org/apache/sqoop/connector/ConnectorManager.java
@@ -22,11 +22,16 @@ import java.net.URL;
 import java.util.ArrayList;
 import java.util.Enumeration;
 import java.util.HashMap;
+import java.util.LinkedList;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
+import java.util.ResourceBundle;
+import java.util.Set;
 
 import org.apache.log4j.Logger;
 import org.apache.sqoop.common.SqoopException;
+import org.apache.sqoop.connector.spi.SqoopConnector;
 import org.apache.sqoop.core.ConfigurationConstants;
 import org.apache.sqoop.repository.Repository;
 import org.apache.sqoop.repository.RepositoryManager;
@@ -44,20 +49,42 @@ public class ConnectorManager {
   private static Map<String, ConnectorHandler> handlerMap =
       new HashMap<String, ConnectorHandler>();
 
-  public static MConnector[] getConnectors() {
-    MConnector[] connectors = new MConnector[handlerMap.size()];
-    int indx = 0;
-    for (ConnectorHandler handler : handlerMap.values()) {
-      connectors[indx++] = handler.getMetadata();
+  public static List<MConnector> getConnectorsMetadata() {
+    List<MConnector> connectors = new LinkedList<MConnector>();
+    for(ConnectorHandler handler : handlerMap.values()) {
+      connectors.add(handler.getMetadata());
     }
     return connectors;
   }
 
-  public static MConnector getConnector(long connectorId) {
+  public static Set<Long> getConnectoIds() {
+    return nameMap.keySet();
+  }
+
+  public static List<ResourceBundle> getResourceBundles(Locale locale) {
+    List<ResourceBundle> bundles = new LinkedList<ResourceBundle>();
+    for(ConnectorHandler handler : handlerMap.values()) {
+      bundles.add(handler.getConnector().getBundle(locale));
+    }
+    return bundles;
+  }
+
+  public static ResourceBundle getResourceBundle(long connectorId,
+                                                 Locale locale) {
+    ConnectorHandler handler = handlerMap.get(nameMap.get(connectorId));
+    return  handler.getConnector().getBundle(locale);
+  }
+
+  public static MConnector getConnectorMetadata(long connectorId) {
     ConnectorHandler handler = handlerMap.get(nameMap.get(connectorId));
     return handler.getMetadata();
   }
 
+  public static SqoopConnector getConnector(long connectorId) {
+    ConnectorHandler handler = handlerMap.get(nameMap.get(connectorId));
+    return handler.getConnector();
+  }
+
   public static synchronized void initialize() {
     if (LOG.isTraceEnabled()) {
       LOG.trace("Begin connector manager initialization");

http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/core/src/main/java/org/apache/sqoop/framework/FrameworkConstants.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/sqoop/framework/FrameworkConstants.java b/core/src/main/java/org/apache/sqoop/framework/FrameworkConstants.java
index e0fa0bf..eb6e8b2 100644
--- a/core/src/main/java/org/apache/sqoop/framework/FrameworkConstants.java
+++ b/core/src/main/java/org/apache/sqoop/framework/FrameworkConstants.java
@@ -31,4 +31,6 @@ public class FrameworkConstants {
     "form-security";
   public static final String FORM_OUTPUT =
     "form-output";
+
+  public static final String RESOURCE_BUNDLE_NAME = "framework-resources";
 }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/core/src/main/java/org/apache/sqoop/framework/FrameworkManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/sqoop/framework/FrameworkManager.java b/core/src/main/java/org/apache/sqoop/framework/FrameworkManager.java
index d2d42d2..657eab2 100644
--- a/core/src/main/java/org/apache/sqoop/framework/FrameworkManager.java
+++ b/core/src/main/java/org/apache/sqoop/framework/FrameworkManager.java
@@ -27,11 +27,14 @@ import org.apache.sqoop.model.MInput;
 import org.apache.sqoop.model.MJobForms;
 import org.apache.sqoop.model.MStringInput;
 import org.apache.sqoop.repository.RepositoryManager;
+import org.apache.sqoop.validation.Validator;
 
 import static org.apache.sqoop.framework.FrameworkConstants.*;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Locale;
+import java.util.ResourceBundle;
 
 /**
  * Manager for Sqoop framework itself.
@@ -50,6 +53,8 @@ public class FrameworkManager {
 
   private static final MFramework mFramework;
 
+  private static final Validator validator;
+
   static {
 
     List<MForm> conForms = new ArrayList<MForm>();
@@ -82,6 +87,9 @@ public class FrameworkManager {
     JOB_FORMS.add(new MJobForms(MJob.Type.EXPORT, jobForms));
 
     mFramework = new MFramework(CONNECTION_FORMS, JOB_FORMS);
+
+    // Build validator
+    validator = new Validator();
   }
 
   public static synchronized void initialize() {
@@ -102,4 +110,12 @@ public class FrameworkManager {
     LOG.trace("Begin framework manager destroy");
   }
 
+  public static Validator getValidator() {
+    return validator;
+  }
+
+  public static ResourceBundle getBundle(Locale locale) {
+    return ResourceBundle.getBundle(
+        FrameworkConstants.RESOURCE_BUNDLE_NAME, locale);
+  }
 }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/core/src/main/java/org/apache/sqoop/repository/JdbcRepository.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/sqoop/repository/JdbcRepository.java b/core/src/main/java/org/apache/sqoop/repository/JdbcRepository.java
index f032141..7a38e4b 100644
--- a/core/src/main/java/org/apache/sqoop/repository/JdbcRepository.java
+++ b/core/src/main/java/org/apache/sqoop/repository/JdbcRepository.java
@@ -41,36 +41,45 @@ public class JdbcRepository implements Repository {
   }
 
   /**
-   * {@inheritDoc}
+   * Private interface to wrap specific code that requires fresh connection to
+   * repository with general code that will get the connection and handle
+   * exceptions.
    */
-  @Override
-  public JdbcRepositoryTransaction getTransaction() {
-    return repoContext.getTransactionFactory().get();
+  private interface DoWithConnection {
+    /**
+     * Do what is needed to be done with given connection object.
+     *
+     * @param conn Connection to metadata repository.
+     * @return Arbitrary value
+     */
+    public Object doIt(Connection conn) throws Exception;
   }
 
   /**
-   * {@inheritDoc}
+   * Handle transaction and connection functionality and delegate action to
+   * given delegator.
+   *
+   * @param delegator Code for specific action
+   * @return Arbitrary value
    */
-  @Override
-  public MConnector registerConnector(MConnector mConnector) {
-    MConnector result = null;
+  private Object doWithConnection(DoWithConnection delegator) {
     JdbcRepositoryTransaction tx = null;
-    String connectorUniqueName = mConnector.getUniqueName();
+
     try {
+      // Get transaction and connection
       tx = getTransaction();
       tx.begin();
       Connection conn = tx.getConnection();
-      result = handler.findConnector(connectorUniqueName, conn);
-      if (result == null) {
-        handler.registerConnector(mConnector, conn);
-      } else {
-        if (!result.equals(mConnector)) {
-          throw new SqoopException(RepositoryError.JDBCREPO_0013,
-              "given[" + mConnector + "] found[" + result + "]");
-        }
-        mConnector.setPersistenceId(result.getPersistenceId());
-      }
+
+      // Delegate the functionality to our delegator
+      Object returnValue = delegator.doIt(conn);
+
+      // Commit transaction
       tx.commit();
+
+      // Return value that the underlying code needs to return
+      return returnValue;
+
     } catch (Exception ex) {
       if (tx != null) {
         tx.rollback();
@@ -78,95 +87,156 @@ public class JdbcRepository implements Repository {
       if (ex instanceof SqoopException) {
         throw (SqoopException) ex;
       }
-      throw new SqoopException(RepositoryError.JDBCREPO_0012,
-          mConnector.toString(), ex);
+      throw new SqoopException(RepositoryError.JDBCREPO_0012, ex);
     } finally {
       if (tx != null) {
         tx.close();
       }
     }
-
-    return result;
   }
 
   /**
    * {@inheritDoc}
    */
   @Override
-  public void registerFramework(MFramework mFramework) {
-    MFramework result = null;
-    JdbcRepositoryTransaction tx = null;
+  public JdbcRepositoryTransaction getTransaction() {
+    return repoContext.getTransactionFactory().get();
+  }
 
-    try {
-      tx = getTransaction();
-      tx.begin();
-      Connection conn = tx.getConnection();
-      result = handler.findFramework(conn);
-      if (result == null) {
-        handler.registerFramework(mFramework, conn);
-      } else {
-        if (!result.equals(mFramework)) {
-          throw new SqoopException(RepositoryError.JDBCREPO_0014,
-              "given[" + mFramework + "] found[" + result + "]");
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public MConnector registerConnector(final MConnector mConnector) {
+
+    return (MConnector) doWithConnection(new DoWithConnection() {
+      @Override
+      public Object doIt(Connection conn) throws Exception {
+        String connectorUniqueName = mConnector.getUniqueName();
+
+        MConnector result = handler.findConnector(connectorUniqueName, conn);
+        if (result == null) {
+          handler.registerConnector(mConnector, conn);
+        } else {
+          if (!result.equals(mConnector)) {
+            throw new SqoopException(RepositoryError.JDBCREPO_0013,
+                "given[" + mConnector + "] found[" + result + "]");
+          }
+          mConnector.setPersistenceId(result.getPersistenceId());
         }
-        mFramework.setPersistenceId(result.getPersistenceId());
-      }
-      tx.commit();
-    } catch (Exception ex) {
-      if (tx != null) {
-        tx.rollback();
-      }
-      if (ex instanceof SqoopException) {
-        throw (SqoopException) ex;
+
+        return result;
       }
-      throw new SqoopException(RepositoryError.JDBCREPO_0012,
-        mFramework.toString(), ex);
-    } finally {
-      if (tx != null) {
-        tx.close();
+    });
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public void registerFramework(final MFramework mFramework) {
+    doWithConnection(new DoWithConnection() {
+      @Override
+      public Object doIt(Connection conn) {
+        MFramework result = handler.findFramework(conn);
+        if (result == null) {
+          handler.registerFramework(mFramework, conn);
+        } else {
+          if (!result.equals(mFramework)) {
+            throw new SqoopException(RepositoryError.JDBCREPO_0014,
+                "given[" + mFramework + "] found[" + result + "]");
+          }
+          mFramework.setPersistenceId(result.getPersistenceId());
+        }
+
+        return null;
       }
-    }
+    });
   }
 
   /**
    * {@inheritDoc}
    */
   @Override
-  public void createConnection(MConnection connection) {
-    // TODO(jarcec): Implement
+  public void createConnection(final MConnection connection) {
+    doWithConnection(new DoWithConnection() {
+      @Override
+      public Object doIt(Connection conn) {
+        if(connection.hasPersistenceId()) {
+          throw new SqoopException(RepositoryError.JDBCREPO_0015);
+        }
+
+        handler.createConnection(connection, conn);
+        return null;
+      }
+    });
   }
 
   /**
    * {@inheritDoc}
    */
   @Override
-  public void updateConnection(MConnection connection) {
-    // TODO(jarcec): Implement
+  public void updateConnection(final MConnection connection) {
+    doWithConnection(new DoWithConnection() {
+      @Override
+      public Object doIt(Connection conn) {
+       if(!connection.hasPersistenceId()) {
+          throw new SqoopException(RepositoryError.JDBCREPO_0016);
+        }
+        if(!handler.existsConnection(connection.getPersistenceId(), conn)) {
+          throw new SqoopException(RepositoryError.JDBCREPO_0017,
+            "Invalid id: " + connection.getPersistenceId());
+        }
+
+        handler.updateConnection(connection, conn);
+        return null;
+      }
+    });
   }
 
   /**
    * {@inheritDoc}
    */
   @Override
-  public void deleteConnection(MConnection connection) {
-    // TODO(jarcec): Implement
+  public void deleteConnection(final long connectionId) {
+    doWithConnection(new DoWithConnection() {
+      @Override
+      public Object doIt(Connection conn) {
+        if(!handler.existsConnection(connectionId, conn)) {
+          throw new SqoopException(RepositoryError.JDBCREPO_0017,
+            "Invalid id: " + connectionId);
+        }
+
+        handler.deleteConnection(connectionId, conn);
+        return null;
+      }
+    });
   }
 
   /**
    * {@inheritDoc}
    */
   @Override
-  public MConnection findConnection(String name) {
-    // TODO(jarcec): Implement
-    return null;
+  public MConnection findConnection(final long connectionId) {
+    return (MConnection) doWithConnection(new DoWithConnection() {
+      @Override
+      public Object doIt(Connection conn) {
+        return handler.findConnection(connectionId, conn);
+      }
+    });
   }
 
   /**
    * {@inheritDoc}
    */
+  @SuppressWarnings("unchecked")
   @Override
-  public List<MConnection> findConnections(MConnector connector) {
-    // TODO(jarcec): Implement
-    return null;
+  public List<MConnection> findConnections() {
+    return (List<MConnection>) doWithConnection(new DoWithConnection() {
+      @Override
+      public Object doIt(Connection conn) {
+        return handler.findConnections(conn);
+      }
+    });
   }
 }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/core/src/main/java/org/apache/sqoop/repository/JdbcRepositoryHandler.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/sqoop/repository/JdbcRepositoryHandler.java b/core/src/main/java/org/apache/sqoop/repository/JdbcRepositoryHandler.java
index b349109..95a0737 100644
--- a/core/src/main/java/org/apache/sqoop/repository/JdbcRepositoryHandler.java
+++ b/core/src/main/java/org/apache/sqoop/repository/JdbcRepositoryHandler.java
@@ -18,7 +18,9 @@
 package org.apache.sqoop.repository;
 
 import java.sql.Connection;
+import java.util.List;
 
+import org.apache.sqoop.model.MConnection;
 import org.apache.sqoop.model.MConnector;
 import org.apache.sqoop.model.MFramework;
 
@@ -104,4 +106,57 @@ public interface JdbcRepositoryHandler {
    *   want to validate live connections.
    */
   public String validationQuery();
+
+  /**
+   * Save given connection to repository. This connection must not be already
+   * present in the repository otherwise exception will be thrown.
+   *
+   * @param connection Connection object to serialize into repository.
+   * @param conn Connection to metadata repository
+   */
+  public void createConnection(MConnection connection, Connection conn);
+
+  /**
+   * Update given connection representation in repository. This connection
+   * object must already exists in the repository otherwise exception will be
+   * thrown.
+   *
+   * @param connection Connection object that should be updated in repository.
+   * @param conn Connection to metadata repository
+   */
+  public void updateConnection(MConnection connection, Connection conn);
+
+  /**
+   * Check if given connection exists in metastore.
+   *
+   * @param id Connection id
+   * @param conn Connection to metadata repository
+   * @return True if the connection exists
+   */
+  public boolean existsConnection(long id, Connection conn);
+
+  /**
+   * Delete connection with given id from metadata repository.
+   *
+   * @param id Connection object that should be removed from repository
+   * @param conn Connection to metadata repository
+   */
+  public void deleteConnection(long id, Connection conn);
+
+  /**
+   * Find connection with given id in repository.
+   *
+   * @param id Connection id
+   * @param conn Connection to metadata repository
+   * @return Deserialized form of the connection that is saved in repository
+   */
+  public MConnection findConnection(long id, Connection conn);
+
+  /**
+   * Get all connection objects.
+   *
+   * @param conn Connection to metadata repository
+   * @return List will all saved connection objects
+   */
+  public List<MConnection> findConnections(Connection conn);
 }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/core/src/main/java/org/apache/sqoop/repository/Repository.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/sqoop/repository/Repository.java b/core/src/main/java/org/apache/sqoop/repository/Repository.java
index ae98410..ef822c4 100644
--- a/core/src/main/java/org/apache/sqoop/repository/Repository.java
+++ b/core/src/main/java/org/apache/sqoop/repository/Repository.java
@@ -77,26 +77,24 @@ public interface Repository {
   public void updateConnection(MConnection connection);
 
   /**
-   * Delete given connection from repository. This connection object must
-   * exists in repository otherwise exception will be thrown.
+   * Delete connection with given id from metadata repository.
    *
-   * @param connection Connection object that should be removed from repository
+   * @param id Connection object that should be removed from repository
    */
-  public void deleteConnection(MConnection connection);
+  public void deleteConnection(long id);
 
   /**
-   * Find connection with given name in repository.
+   * Find connection with given id in repository.
    *
-   * @param name Connection name
+   * @param id Connection id
    * @return Deserialized form of the connection that is saved in repository
    */
-  public MConnection findConnection(String name);
+  public MConnection findConnection(long id);
 
   /**
-   * Get all connection objects for given connector.
+   * Get all connection objects.
    *
-   * @param connector Connector object
    * @return Array will all saved connection objects
    */
-  public List<MConnection> findConnections(MConnector connector);
+  public List<MConnection> findConnections();
 }

http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/core/src/main/java/org/apache/sqoop/repository/RepositoryError.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/sqoop/repository/RepositoryError.java b/core/src/main/java/org/apache/sqoop/repository/RepositoryError.java
index f6b1a33..6d6f729 100644
--- a/core/src/main/java/org/apache/sqoop/repository/RepositoryError.java
+++ b/core/src/main/java/org/apache/sqoop/repository/RepositoryError.java
@@ -73,14 +73,24 @@ public enum RepositoryError implements ErrorCode {
    */
   JDBCREPO_0011("Attempt to reinitialize JDBC repository context"),
 
-  /** The system was unable to register metadata in its repository. */
-  JDBCREPO_0012("Failure in repository metadata registration process."),
+  /** Failure in metadata repository operation. */
+  JDBCREPO_0012("Failure in metadata repository operation."),
 
   /** The system found a change in connector metadata that requires upgrade. */
   JDBCREPO_0013("Connector metadata changed - upgrade may be required"),
 
   /** The system found a change in framework metadata that requires upgrade. */
-  JDBCREPO_0014("Framework metadata changed - upgrade may be required");
+  JDBCREPO_0014("Framework metadata changed - upgrade may be required"),
+
+  /** Connection that we're trying to create is already saved in repository **/
+  JDBCREPO_0015("Cannot create connection that was already created"),
+
+  /** Connection that we're trying to update is not yet saved **/
+  JDBCREPO_0016("Cannot update connection that was not yet created"),
+
+  /** Invalid connection id **/
+  JDBCREPO_0017("Given connection id is invalid"),
+  ;
 
   private final String message;
 

http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/core/src/main/resources/framework-resources.properties
----------------------------------------------------------------------
diff --git a/core/src/main/resources/framework-resources.properties b/core/src/main/resources/framework-resources.properties
new file mode 100644
index 0000000..577b7aa
--- /dev/null
+++ b/core/src/main/resources/framework-resources.properties
@@ -0,0 +1,36 @@
+# 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.
+
+# Framework Resources
+
+############################
+# Security Form
+#
+form-security-label = Security related configuration options
+form-security-help = You must supply the information requested in order to \
+                   create a job object.
+
+inp-conn-max-connections-label = Max connections
+inp-conn-max-connections-help = Maximal number of connections that this \
+                                connection object can use at one point in time
+
+# Output From
+#
+form-output-label = Output configuration
+form-output-help = You must supply the information requested in order to \
+                   get information where you want to store your data.
+
+inp-conn-output-format-label = Output format
+inp-conn-output-format-help = Output format that should be used

http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/repository/repository-derby/src/main/java/org/apache/sqoop/repository/derby/DerbyRepoError.java
----------------------------------------------------------------------
diff --git a/repository/repository-derby/src/main/java/org/apache/sqoop/repository/derby/DerbyRepoError.java b/repository/repository-derby/src/main/java/org/apache/sqoop/repository/derby/DerbyRepoError.java
index ae400cd..620561d 100644
--- a/repository/repository-derby/src/main/java/org/apache/sqoop/repository/derby/DerbyRepoError.java
+++ b/repository/repository-derby/src/main/java/org/apache/sqoop/repository/derby/DerbyRepoError.java
@@ -55,7 +55,7 @@ public enum DerbyRepoError implements ErrorCode {
    * The system could not load the connector due to unexpected position
    * of form.
    */
-  DERBYREPO_0010("The form retrieved does not match expteced position"),
+  DERBYREPO_0010("The form retrieved does not match expected position"),
 
   /**
    * The system was not able to register metadata due to a pre-assigned
@@ -70,10 +70,10 @@ public enum DerbyRepoError implements ErrorCode {
   DERBYREPO_0012("Unexpected update count on connector registration"),
 
   /**
-   * The system was unable to register connector metadata due to a failure to
-   * retrieve the generated identifier.
+   * The system was unable to register metadata due to a failure to retrieve
+   * the generated identifier.
    */
-  DERBYREPO_0013("Unable to retrieve generated identifier for new connector"),
+  DERBYREPO_0013("Unable to retrieve generated identifier"),
 
   /**
    * The system was unable to register connector metadata due to a server
@@ -103,8 +103,30 @@ public enum DerbyRepoError implements ErrorCode {
    * The system was unable to register connector metadata due to a failure to
    * retrieve the generated identifier for a form input.
    */
-  DERBYREPO_0018("Unable to retrieve generated identifier for form input");
+  DERBYREPO_0018("Unable to retrieve generated identifier for form input"),
+
+  /** We cant create new connection in metastore **/
+  DERBYREPO_0019("Unable to create new connection data"),
+
+  /** We can't save values for input to metastore **/
+  DERBYREPO_0020("Unable to save input values to metadata repository"),
+
+  /** We can't update connection in metastore **/
+  DERBYREPO_0021("Unable to update connection metadata in repository"),
+
+  /** We can't delete connection in metastore **/
+  DERBYREPO_0022("Unable to delete connection metadata in repository"),
+
+  /** We can't restore connection metadata from metastore **/
+  DERBYREPO_0023("Unable to load connection metadata from repository"),
+
+  /** We can't restore specific connection metadata from metastore **/
+  DERBYREPO_0024("Unable to load specific connection metadata from repository"),
+
+  /** We're unable to check if given connection already exists */
+  DERBYREPO_0025("Unable to check if given connection exists"),
 
+  ;
 
   private final String message;
 

http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/repository/repository-derby/src/main/java/org/apache/sqoop/repository/derby/DerbyRepositoryHandler.java
----------------------------------------------------------------------
diff --git a/repository/repository-derby/src/main/java/org/apache/sqoop/repository/derby/DerbyRepositoryHandler.java b/repository/repository-derby/src/main/java/org/apache/sqoop/repository/derby/DerbyRepositoryHandler.java
index bf52919..75edb2a 100644
--- a/repository/repository-derby/src/main/java/org/apache/sqoop/repository/derby/DerbyRepositoryHandler.java
+++ b/repository/repository-derby/src/main/java/org/apache/sqoop/repository/derby/DerbyRepositoryHandler.java
@@ -35,6 +35,7 @@ import javax.sql.DataSource;
 
 import org.apache.log4j.Logger;
 import org.apache.sqoop.common.SqoopException;
+import org.apache.sqoop.model.MConnection;
 import org.apache.sqoop.model.MConnectionForms;
 import org.apache.sqoop.model.MJob;
 import org.apache.sqoop.model.MJobForms;
@@ -95,7 +96,7 @@ public class DerbyRepositoryHandler implements JdbcRepositoryHandler {
       int baseConnectorCount = baseConnectorStmt.executeUpdate();
       if (baseConnectorCount != 1) {
         throw new SqoopException(DerbyRepoError.DERBYREPO_0012,
-            new Integer(baseConnectorCount).toString());
+          Integer.toString(baseConnectorCount));
       }
 
       ResultSet rsetConnectorId = baseConnectorStmt.getGeneratedKeys();
@@ -127,27 +128,7 @@ public class DerbyRepositoryHandler implements JdbcRepositoryHandler {
       throw new SqoopException(DerbyRepoError.DERBYREPO_0014,
           mc.toString(), ex);
     } finally {
-      if (baseConnectorStmt != null) {
-        try {
-          baseConnectorStmt.close();
-        } catch (SQLException ex) {
-          LOG.error("Unable to close base connector statement", ex);
-        }
-      }
-      if (baseFormStmt != null) {
-        try {
-          baseFormStmt.close();
-        } catch (SQLException ex) {
-          LOG.error("Unable to close base form statement", ex);
-        }
-      }
-      if (baseInputStmt != null) {
-        try {
-          baseInputStmt.close();
-        } catch (SQLException ex) {
-          LOG.error("Unable to close base input statement", ex);
-        }
-      }
+      closeStatements(baseConnectorStmt, baseFormStmt, baseInputStmt);
     }
   }
 
@@ -200,7 +181,6 @@ public class DerbyRepositoryHandler implements JdbcRepositoryHandler {
             + "URL is of an unexpected form: " + connectUrl + ". Therfore no "
             + "attempt will be made to shutdown embedded Derby instance.");
       }
-
     }
   }
 
@@ -249,13 +229,7 @@ public class DerbyRepositoryHandler implements JdbcRepositoryHandler {
       }
       throw new SqoopException(DerbyRepoError.DERBYREPO_0001, ex);
     } finally {
-      if (stmt != null) {
-        try {
-          stmt.close();
-        } catch(SQLException ex) {
-          LOG.error("Unable to  close schema lookup stmt", ex);
-        }
-      }
+      closeStatements(stmt);
       if (connection != null) {
         try {
           connection.close();
@@ -302,8 +276,7 @@ public class DerbyRepositoryHandler implements JdbcRepositoryHandler {
       Map<MJob.Type, List<MForm>> jobForms =
         new HashMap<MJob.Type, List<MForm>>();
 
-      loadForms(shortName, connectionForms, jobForms,
-        formFetchStmt, inputFetchStmt);
+      loadForms(connectionForms, jobForms, formFetchStmt, inputFetchStmt);
 
       mc = new MConnector(connectorName, connectorClassName,
         new MConnectionForms(connectionForms),
@@ -316,27 +289,8 @@ public class DerbyRepositoryHandler implements JdbcRepositoryHandler {
     } catch (SQLException ex) {
       throw new SqoopException(DerbyRepoError.DERBYREPO_0004, shortName, ex);
     } finally {
-      if (baseConnectorFetchStmt != null) {
-        try {
-          baseConnectorFetchStmt.close();
-        } catch (SQLException ex) {
-          LOG.error("Unable to close base connector fetch statement", ex);
-        }
-      }
-      if (formFetchStmt != null) {
-        try {
-          formFetchStmt.close();
-        } catch (SQLException ex) {
-          LOG.error("Unable to close form fetch statement", ex);
-        }
-      }
-      if (inputFetchStmt != null) {
-        try {
-          inputFetchStmt.close();
-        } catch (SQLException ex) {
-          LOG.error("Unable to close input fetch statement", ex);
-        }
-      }
+      closeStatements(baseConnectorFetchStmt,
+        formFetchStmt, inputFetchStmt);
     }
 
     LOG.debug("Looking up connector: " + shortName + ", found: " + mc);
@@ -378,20 +332,7 @@ public class DerbyRepositoryHandler implements JdbcRepositoryHandler {
       throw new SqoopException(DerbyRepoError.DERBYREPO_0014,
           mf.toString(), ex);
     } finally {
-      if (baseFormStmt != null) {
-        try {
-          baseFormStmt.close();
-        } catch (SQLException ex) {
-          LOG.error("Unable to close base form statement", ex);
-        }
-      }
-      if (baseInputStmt != null) {
-        try {
-          baseInputStmt.close();
-        } catch (SQLException ex) {
-          LOG.error("Unable to close base input statement", ex);
-        }
-      }
+      closeStatements(baseFormStmt, baseInputStmt);
     }
   }
 
@@ -412,8 +353,7 @@ public class DerbyRepositoryHandler implements JdbcRepositoryHandler {
       Map<MJob.Type, List<MForm>> jobForms =
         new HashMap<MJob.Type, List<MForm>>();
 
-      loadForms("Framework metadata", connectionForms, jobForms,
-        formFetchStmt, inputFetchStmt);
+      loadForms(connectionForms, jobForms, formFetchStmt, inputFetchStmt);
 
       // Return nothing If there aren't any framework metadata
       if(connectionForms.isEmpty() && jobForms.isEmpty()) {
@@ -461,6 +401,214 @@ public class DerbyRepositoryHandler implements JdbcRepositoryHandler {
     return "values(1)"; // Yes, this is valid derby SQL
   }
 
+  @Override
+  public void createConnection(MConnection connection, Connection conn) {
+    PreparedStatement stmt = null;
+    int result;
+    try {
+      stmt = conn.prepareStatement(STMT_INSERT_CONNECTION,
+        Statement.RETURN_GENERATED_KEYS);
+      stmt.setString(1, connection.getName());
+      stmt.setLong(2, connection.getConnectorId());
+
+      result = stmt.executeUpdate();
+      if (result != 1) {
+        throw new SqoopException(DerbyRepoError.DERBYREPO_0012,
+          Integer.toString(result));
+      }
+
+      ResultSet rsetConnectionId = stmt.getGeneratedKeys();
+
+      if (!rsetConnectionId.next()) {
+        throw new SqoopException(DerbyRepoError.DERBYREPO_0013);
+      }
+
+      long connectionId = rsetConnectionId.getLong(1);
+
+      createConnectionInputs(connectionId,
+                             connection.getConnectorPart().getForms(),
+                             conn);
+      createConnectionInputs(connectionId,
+                             connection.getFrameworkPart().getForms(),
+                             conn);
+
+    } catch (SQLException ex) {
+      throw new SqoopException(DerbyRepoError.DERBYREPO_0019, ex);
+    } finally {
+      closeStatements(stmt);
+    }
+  }
+
+  @Override
+  public void updateConnection(MConnection connection, Connection conn) {
+    // We're not allowing updating values in SQ_CONNECTION (name, connector id)
+    // TODO(jarcec): Remove this limitation
+    // TODO(jarcec): check that connector and other values are not changed!
+
+    PreparedStatement stmt = null;
+    try {
+      // Firstly remove old values
+      stmt = conn.prepareStatement(STMT_DELETE_CONNECTION_INPUT);
+      stmt.setLong(1, connection.getPersistenceId());
+      stmt.executeUpdate();
+
+      // And reinsert new ones
+      createConnectionInputs(connection.getPersistenceId(),
+                             connection.getConnectorPart().getForms(),
+                             conn);
+      createConnectionInputs(connection.getPersistenceId(),
+                             connection.getFrameworkPart().getForms(),
+                             conn);
+
+    } catch (SQLException ex) {
+      throw new SqoopException(DerbyRepoError.DERBYREPO_0021, ex);
+    } finally {
+      closeStatements(stmt);
+    }
+  }
+
+  @Override
+  public boolean existsConnection(long id, Connection conn) {
+    PreparedStatement stmt = null;
+    ResultSet rs = null;
+    try {
+      stmt = conn.prepareStatement(STMT_SELECT_CONNECTION_CHECK);
+      stmt.setLong(1, id);
+      rs = stmt.executeQuery();
+
+      // Should be always valid in query with count
+      rs.next();
+
+      return rs.getLong(1) == 1;
+    } catch (SQLException ex) {
+      throw new SqoopException(DerbyRepoError.DERBYREPO_0025, ex);
+    } finally {
+      closeResultSets(rs);
+      closeStatements(stmt);
+    }
+  }
+
+  @Override
+  public void deleteConnection(long id, Connection conn) {
+    PreparedStatement dltConn = null;
+    PreparedStatement dltConnInput = null;
+    try {
+      dltConnInput = conn.prepareStatement(STMT_DELETE_CONNECTION_INPUT);
+      dltConn = conn.prepareStatement(STMT_DELETE_CONNECTION);
+
+      dltConnInput.setLong(1, id);
+      dltConn.setLong(1, id);
+
+      dltConnInput.executeUpdate();
+      dltConn.executeUpdate();
+
+    } catch (SQLException ex) {
+      throw new SqoopException(DerbyRepoError.DERBYREPO_0022, ex);
+    } finally {
+      closeStatements(dltConn, dltConnInput);
+    }
+  }
+
+  @Override
+  public MConnection findConnection(long id, Connection conn) {
+    PreparedStatement stmt = null;
+    try {
+      stmt = conn.prepareStatement(STMT_SELECT_CONNECTION_SINGLE);
+      stmt.setLong(1, id);
+
+      List<MConnection> connections = loadConnections(stmt, conn);
+
+      if(connections.size() != 1) {
+        throw new SqoopException(DerbyRepoError.DERBYREPO_0024, "Couldn't find"
+          + " connection with id " + id);
+      }
+
+      // Return the first and only one connection object
+      return connections.get(0);
+
+    } catch (SQLException ex) {
+      throw new SqoopException(DerbyRepoError.DERBYREPO_0023, ex);
+    } finally {
+      closeStatements(stmt);
+    }
+  }
+
+  @Override
+  public List<MConnection> findConnections(Connection conn) {
+    PreparedStatement stmt = null;
+    try {
+      stmt = conn.prepareStatement(STMT_SELECT_CONNECTION_ALL);
+
+      return loadConnections(stmt, conn);
+
+    } catch (SQLException ex) {
+      throw new SqoopException(DerbyRepoError.DERBYREPO_0023, ex);
+    } finally {
+      closeStatements(stmt);
+    }
+  }
+
+  private List<MConnection> loadConnections(PreparedStatement stmt,
+                                            Connection conn)
+                                            throws SQLException {
+    List<MConnection> connections = new ArrayList<MConnection>();
+    ResultSet rsConnection = null;
+    PreparedStatement formConnectorFetchStmt = null;
+    PreparedStatement formFrameworkFetchStmt = null;
+    PreparedStatement inputFetchStmt = null;
+
+    try {
+      rsConnection = stmt.executeQuery();
+
+      while(rsConnection.next()) {
+        long id = rsConnection.getLong(1);
+        String name = rsConnection.getString(2);
+        long connectorId = rsConnection.getLong(3);
+
+        formConnectorFetchStmt =
+          conn.prepareStatement(STMT_FETCH_FORM_CONNECTOR);
+        formConnectorFetchStmt.setLong(1, connectorId);
+
+        formFrameworkFetchStmt =
+          conn.prepareStatement(STMT_FETCH_FORM_FRAMEWORK);
+
+        LOG.error(STMT_FETCH_CONNECTION_INPUT);
+
+        inputFetchStmt = conn.prepareStatement(STMT_FETCH_CONNECTION_INPUT);
+        //inputFetchStmt.setLong(1, XXX); // Will be filled by loadForms
+        inputFetchStmt.setLong(2, id);
+
+        List<MForm> connectorConnForms = new ArrayList<MForm>();
+        List<MForm> frameworkConnForms = new ArrayList<MForm>();
+
+        Map<MJob.Type, List<MForm>> connectorJobForms
+          = new HashMap<MJob.Type, List<MForm>>();
+        Map<MJob.Type, List<MForm>> frameworkJobForms
+          = new HashMap<MJob.Type, List<MForm>>();
+
+        loadForms(connectorConnForms, connectorJobForms,
+          formConnectorFetchStmt, inputFetchStmt);
+        loadForms(frameworkConnForms, frameworkJobForms,
+          formFrameworkFetchStmt, inputFetchStmt);
+
+        MConnection connection = new MConnection(connectorId,
+          new MConnectionForms(connectorConnForms),
+          new MConnectionForms(frameworkConnForms));
+
+        connection.setPersistenceId(id);
+        connection.setName(name);
+
+        connections.add(connection);
+      }
+    } finally {
+      closeResultSets(rsConnection);
+      closeStatements(formConnectorFetchStmt,
+        formFrameworkFetchStmt, inputFetchStmt);
+    }
+
+    return connections;
+  }
+
   /**
    * Register forms in derby database.
    *
@@ -609,15 +757,13 @@ public class DerbyRepositoryHandler implements JdbcRepositoryHandler {
    * Use given prepared statements to load all forms and corresponding inputs
    * from Derby.
    *
-   * @param connectorName Connector name for purpose of printing errors
    * @param connectionForms List of connection forms that will be filled up
    * @param jobForms Map with job forms that will be filled up
    * @param formFetchStmt Prepared statement for fetching forms
    * @param inputFetchStmt Prepare statement for fetching inputs
    * @throws SQLException In case of any failure on Derby side
    */
-  public void loadForms(String connectorName,
-                        List<MForm> connectionForms,
+  public void loadForms(List<MForm> connectionForms,
                         Map<MJob.Type, List<MForm>> jobForms,
                         PreparedStatement formFetchStmt,
                         PreparedStatement inputFetchStmt) throws SQLException {
@@ -647,6 +793,7 @@ public class DerbyRepositoryHandler implements JdbcRepositoryHandler {
         String inputType = rsetInput.getString(5);
         boolean inputStrMask = rsetInput.getBoolean(6);
         short inputStrLength = rsetInput.getShort(7);
+        String value = rsetInput.getString(8);
 
         MInputType mit = MInputType.valueOf(inputType);
 
@@ -663,8 +810,17 @@ public class DerbyRepositoryHandler implements JdbcRepositoryHandler {
               "input-" + inputName + ":" + inputId + ":"
               + "form-" + inputForm + ":" + mit.name());
         }
+
+        // Set persistent ID
         input.setPersistenceId(inputId);
 
+        // Set value
+        if(value == null) {
+          input.setEmpty();
+        } else {
+          input.restoreFromUrlSafeValueString(value);
+        }
+
         if (mf.getInputs().size() != inputIndex) {
           throw new SqoopException(DerbyRepoError.DERBYREPO_0009,
               "form: " + mf + "; input: " + input);
@@ -675,7 +831,7 @@ public class DerbyRepositoryHandler implements JdbcRepositoryHandler {
 
       if (mf.getInputs().size() == 0) {
         throw new SqoopException(DerbyRepoError.DERBYREPO_0008,
-            "connector-" + formConnectorId + ":" + mf);
+            "connector-" + formConnectorId + ": " + mf);
       }
 
       MFormType mft = MFormType.valueOf(formType);
@@ -683,7 +839,7 @@ public class DerbyRepositoryHandler implements JdbcRepositoryHandler {
       case CONNECTION:
         if (connectionForms.size() != formIndex) {
           throw new SqoopException(DerbyRepoError.DERBYREPO_0010,
-              "connector: " + connectorName + "; form: " + mf);
+              "connector-i" + formConnectorId + "; form: " + mf);
         }
         connectionForms.add(mf);
         break;
@@ -695,7 +851,7 @@ public class DerbyRepositoryHandler implements JdbcRepositoryHandler {
 
         if (jobForms.get(jobType).size() != formIndex) {
           throw new SqoopException(DerbyRepoError.DERBYREPO_0010,
-              "connector: " + connectorName + "; form: " + mf);
+              "connector-" + formConnectorId + "; form: " + mf);
         }
         jobForms.get(jobType).add(mf);
         break;
@@ -718,4 +874,72 @@ public class DerbyRepositoryHandler implements JdbcRepositoryHandler {
 
     return ret;
   }
+
+  private void createConnectionInputs(long connectionId,
+                                      List<MForm> forms,
+                                      Connection conn) throws SQLException {
+    PreparedStatement stmt = null;
+    int result;
+
+    try {
+      stmt = conn.prepareStatement(STMT_INSERT_CONNECTION_INPUT);
+
+      for (MForm form : forms) {
+        for (MInput input : form.getInputs()) {
+          // Skip empty values as we're not interested in storing those in db
+          if (input.isEmpty()) {
+            continue;
+          }
+          stmt.setLong(1, connectionId);
+          stmt.setLong(2, input.getPersistenceId());
+          stmt.setString(3, input.getUrlSafeValueString());
+
+          result = stmt.executeUpdate();
+          if (result != 1) {
+            throw new SqoopException(DerbyRepoError.DERBYREPO_0020,
+              Integer.toString(result));
+          }
+        }
+      }
+    } finally {
+      closeStatements(stmt);
+    }
+  }
+
+  /**
+   * Close all given Results set.
+   *
+   * Any occurring exception is silently ignored and logged.
+   *
+   * @param resultSets Result sets to close
+   */
+  private void closeResultSets(ResultSet ... resultSets) {
+    for (ResultSet rs : resultSets) {
+      if(rs != null) {
+        try {
+          rs.close();
+        } catch(SQLException ex) {
+          LOG.error("Exception during closing result set", ex);
+        }
+      }
+    }
+  }
+
+  /**
+   * Close all given statements.
+   *
+   * Any occurring exception is silently ignored and logged.
+   *
+   * @param stmts Statements to close
+   */  private void closeStatements(Statement... stmts) {
+    for (Statement stmt : stmts) {
+      if(stmt != null) {
+        try {
+          stmt.close();
+        } catch (SQLException ex) {
+          LOG.error("Exception during closing statement", ex);
+        }
+      }
+    }
+  }
 }


Mime
View raw message