You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sqoop.apache.org by bl...@apache.org on 2012/09/07 21:48:36 UTC
[1/3] git commit: SQOOP-596: Implement connection resource end-to-end
Updated Branches:
refs/heads/sqoop2 1f9bb28e0 -> 47cb311a5
SQOOP-596: Implement connection resource end-to-end
Project: http://git-wip-us.apache.org/repos/asf/sqoop/repo
Commit: http://git-wip-us.apache.org/repos/asf/sqoop/commit/47cb311a
Tree: http://git-wip-us.apache.org/repos/asf/sqoop/tree/47cb311a
Diff: http://git-wip-us.apache.org/repos/asf/sqoop/diff/47cb311a
Branch: refs/heads/sqoop2
Commit: 47cb311a5f25791d9b58d3ffcd2a37c79fa4e7ac
Parents: 1f9bb28
Author: Bilung Lee <bl...@apache.org>
Authored: Fri Sep 7 12:40:34 2012 -0700
Committer: Bilung Lee <bl...@apache.org>
Committed: Fri Sep 7 12:40:34 2012 -0700
----------------------------------------------------------------------
.../org/apache/sqoop/client/core/ClientError.java | 10 +-
.../apache/sqoop/client/display/FormDisplayer.java | 91 ----
.../sqoop/client/request/ConnectionRequest.java | 82 ++++
.../sqoop/client/request/ConnectorRequest.java | 15 +-
.../sqoop/client/request/FrameworkRequest.java | 10 +-
.../org/apache/sqoop/client/request/Request.java | 73 +++-
.../sqoop/client/request/VersionRequest.java | 2 +-
.../apache/sqoop/client/shell/CreateCommand.java | 58 +++
.../client/shell/CreateConnectionFunction.java | 156 ++++++
.../apache/sqoop/client/shell/DeleteCommand.java | 58 +++
.../client/shell/DeleteConnectionFunction.java | 67 +++
.../org/apache/sqoop/client/shell/ShowCommand.java | 6 +-
.../sqoop/client/shell/ShowConnectionFunction.java | 107 ++++
.../sqoop/client/shell/ShowConnectorFunction.java | 17 +-
.../sqoop/client/shell/ShowFrameworkFunction.java | 10 +-
.../org/apache/sqoop/client/shell/SqoopShell.java | 9 +-
.../apache/sqoop/client/shell/UpdateCommand.java | 58 +++
.../client/shell/UpdateConnectionFunction.java | 136 ++++++
.../apache/sqoop/client/utils/FormDisplayer.java | 135 ++++++
.../org/apache/sqoop/client/utils/FormFiller.java | 132 +++++
.../org/apache/sqoop/common/ExceptionInfo.java | 64 ---
.../java/org/apache/sqoop/json/ConnectionBean.java | 177 +++++++
.../java/org/apache/sqoop/json/ConnectorBean.java | 32 +-
.../java/org/apache/sqoop/json/ExceptionInfo.java | 73 +++
.../java/org/apache/sqoop/json/FrameworkBean.java | 15 +-
.../java/org/apache/sqoop/json/ValidationBean.java | 143 ++++++
.../apache/sqoop/json/util/FormSerialization.java | 33 +-
.../json/util/ResourceBundleSerialization.java | 83 ++++
.../java/org/apache/sqoop/model/MConnection.java | 39 ++-
.../main/java/org/apache/sqoop/model/MInput.java | 15 +
.../java/org/apache/sqoop/model/MMapInput.java | 10 +
.../java/org/apache/sqoop/model/MStringInput.java | 10 +
.../org/apache/sqoop/utils/MapResourceBundle.java | 49 ++
.../java/org/apache/sqoop/validation/Status.java | 69 +++
.../org/apache/sqoop/json/TestConnectionBean.java | 66 +++
.../org/apache/sqoop/json/TestConnectorBean.java | 65 +--
.../org/apache/sqoop/json/TestFrameworkBean.java | 54 +--
.../test/java/org/apache/sqoop/json/TestUtil.java | 137 ++++++
.../org/apache/sqoop/json/TestValidationBean.java | 69 +++
.../apache/sqoop/utils/TestMapResourceBundle.java | 41 ++
.../org/apache/sqoop/validation/TestStatus.java | 53 ++
.../sqoop/connector/jdbc/GenericJdbcConnector.java | 3 +-
.../jdbc/GenericJdbcConnectorConstants.java | 3 +-
.../sqoop/connector/jdbc/GenericJdbcValidator.java | 63 +++
.../generic-jdbc-connector-resources.properties | 12 +-
.../connector/mysqljdbc/MySqlJdbcConnector.java | 5 +-
.../apache/sqoop/connector/ConnectorHandler.java | 4 +
.../apache/sqoop/connector/ConnectorManager.java | 39 ++-
.../apache/sqoop/framework/FrameworkConstants.java | 2 +
.../apache/sqoop/framework/FrameworkManager.java | 16 +
.../apache/sqoop/repository/JdbcRepository.java | 198 +++++---
.../sqoop/repository/JdbcRepositoryHandler.java | 55 +++
.../org/apache/sqoop/repository/Repository.java | 18 +-
.../apache/sqoop/repository/RepositoryError.java | 16 +-
.../main/resources/framework-resources.properties | 36 ++
.../sqoop/repository/derby/DerbyRepoError.java | 32 +-
.../repository/derby/DerbyRepositoryHandler.java | 374 ++++++++++++---
.../sqoop/repository/derby/DerbySchemaQuery.java | 62 +++-
.../sqoop/handler/ConnectionRequestHandler.java | 208 ++++++++
.../sqoop/handler/ConnectorRequestHandler.java | 30 +-
.../sqoop/handler/FrameworkRequestHandler.java | 5 +-
.../org/apache/sqoop/server/RequestContext.java | 51 ++
.../apache/sqoop/server/SqoopProtocolServlet.java | 58 ++-
.../apache/sqoop/server/common/ServerError.java | 51 ++
.../apache/sqoop/server/v1/ConnectionServlet.java | 56 +++
server/src/main/webapp/WEB-INF/web.xml | 12 +
.../java/org/apache/sqoop/validation/Status.java | 45 --
.../org/apache/sqoop/validation/Validator.java | 5 +-
68 files changed, 3449 insertions(+), 539 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/client/src/main/java/org/apache/sqoop/client/core/ClientError.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/sqoop/client/core/ClientError.java b/client/src/main/java/org/apache/sqoop/client/core/ClientError.java
index 91d1aee..1cf42e4 100644
--- a/client/src/main/java/org/apache/sqoop/client/core/ClientError.java
+++ b/client/src/main/java/org/apache/sqoop/client/core/ClientError.java
@@ -34,7 +34,15 @@ public enum ClientError implements ErrorCode {
CLIENT_0003("An error has occurred when parsing options"),
/** Unable to resolve the variables. */
- CLIENT_0004("Unable to resolve the variables");
+ CLIENT_0004("Unable to resolve the variables"),
+
+ /** We're not able to get user input */
+ CLIENT_0005("Can't get user input"),
+
+ /** There occured exception on server side **/
+ CLIENT_0006("Server has returned exception"),
+
+ ;
private final String message;
http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/client/src/main/java/org/apache/sqoop/client/display/FormDisplayer.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/sqoop/client/display/FormDisplayer.java b/client/src/main/java/org/apache/sqoop/client/display/FormDisplayer.java
deleted file mode 100644
index 6e632d4..0000000
--- a/client/src/main/java/org/apache/sqoop/client/display/FormDisplayer.java
+++ /dev/null
@@ -1,91 +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.client.display;
-
-import org.apache.sqoop.model.MForm;
-import org.apache.sqoop.model.MFramework;
-import org.apache.sqoop.model.MInput;
-import org.apache.sqoop.model.MInputType;
-import org.apache.sqoop.model.MJobForms;
-import org.apache.sqoop.model.MStringInput;
-import org.codehaus.groovy.tools.shell.IO;
-
-import java.util.Iterator;
-import java.util.List;
-
-/**
- * Convenience static methods for displaying form related information
- */
-public class FormDisplayer {
-
- public static void displayFormDetails(IO io, MFramework framework) {
- io.out.print(" Supported job types: ");
- io.out.println(framework.getAllJobsForms().keySet().toString());
-
- displayForms(io, framework.getConnectionForms().getForms(), "Connection");
-
- for (MJobForms jobForms : framework.getAllJobsForms().values()) {
- io.out.print(" Forms for job type ");
- io.out.print(jobForms.getType().name());
- io.out.println(":");
-
- displayForms(io, jobForms.getForms(), "Job");
- }
- }
-
- public static void displayForms(IO io, List<MForm> forms, String type) {
- Iterator<MForm> fiter = forms.iterator();
- int findx = 1;
- while (fiter.hasNext()) {
- io.out.print(" ");
- io.out.print(type);
- io.out.print(" form ");
- io.out.print(findx++);
- io.out.println(":");
-
- MForm form = fiter.next();
- io.out.print(" Name: ");
- io.out.println(form.getName());
-
- List<MInput<?>> inputs = form.getInputs();
- Iterator<MInput<?>> iiter = inputs.iterator();
- int iindx = 1;
- while (iiter.hasNext()) {
- io.out.print(" Input ");
- io.out.print(iindx++);
- io.out.println(":");
-
- MInput<?> input = iiter.next();
- io.out.print(" Name: ");
- io.out.println(input.getName());
- io.out.print(" Type: ");
- io.out.println(input.getType());
- if (input.getType() == MInputType.STRING) {
- io.out.print(" Mask: ");
- io.out.println(((MStringInput)input).isMasked());
- io.out.print(" Size: ");
- io.out.println(((MStringInput)input).getMaxLength());
- }
- }
- }
- }
-
- private FormDisplayer() {
- // Do not instantiate
- }
-}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/client/src/main/java/org/apache/sqoop/client/request/ConnectionRequest.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/sqoop/client/request/ConnectionRequest.java b/client/src/main/java/org/apache/sqoop/client/request/ConnectionRequest.java
new file mode 100644
index 0000000..80a84cd
--- /dev/null
+++ b/client/src/main/java/org/apache/sqoop/client/request/ConnectionRequest.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.client.request;
+
+import org.apache.sqoop.json.ConnectionBean;
+import org.apache.sqoop.json.ValidationBean;
+import org.apache.sqoop.model.MConnection;
+import org.apache.sqoop.validation.Status;
+import org.json.simple.JSONObject;
+import org.json.simple.JSONValue;
+
+/**
+ * Provide CRUD semantics over RESTfull HTTP API for connections. All operations
+ * are normally supported.
+ */
+public class ConnectionRequest extends Request {
+
+ public static final String RESOURCE = "v1/connection/";
+
+ public ConnectionBean read(String serverUrl, String xid) {
+ String response = null;
+ if (xid == null) {
+ response = super.get(serverUrl + RESOURCE + "all");
+ } else {
+ response = super.get(serverUrl + RESOURCE + xid);
+ }
+ JSONObject jsonObject = (JSONObject)JSONValue.parse(response);
+
+ ConnectionBean connectionBean = new ConnectionBean();
+ connectionBean.restore(jsonObject);
+
+ return connectionBean;
+ }
+
+ public Status create(String serverUrl, MConnection connection) {
+
+ ConnectionBean connectionBean = new ConnectionBean(connection);
+ JSONObject connectionJson = connectionBean.extract();
+
+ String response = super.post(serverUrl + RESOURCE,
+ connectionJson.toJSONString());
+
+ ValidationBean validationBean = new ValidationBean(connection);
+ validationBean.restore((JSONObject) JSONValue.parse(response));
+
+ return validationBean.getStatus();
+ }
+
+ public Status update(String serverUrl, MConnection connection) {
+
+ ConnectionBean connectionBean = new ConnectionBean(connection);
+ JSONObject connectionJson = connectionBean.extract();
+
+ String response = super.put(serverUrl + RESOURCE
+ + connection.getPersistenceId(),
+ connectionJson.toJSONString());
+
+ ValidationBean validationBean = new ValidationBean(connection);
+ validationBean.restore((JSONObject) JSONValue.parse(response));
+
+ return validationBean.getStatus();
+ }
+
+ public void delete(String serverUrl, long id) {
+ super.delete(serverUrl + RESOURCE + id);
+ }
+}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/client/src/main/java/org/apache/sqoop/client/request/ConnectorRequest.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/sqoop/client/request/ConnectorRequest.java b/client/src/main/java/org/apache/sqoop/client/request/ConnectorRequest.java
index 2866700..9ea9d5d 100644
--- a/client/src/main/java/org/apache/sqoop/client/request/ConnectorRequest.java
+++ b/client/src/main/java/org/apache/sqoop/client/request/ConnectorRequest.java
@@ -21,14 +21,21 @@ import org.apache.sqoop.json.ConnectorBean;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
+/**
+ * Provide cRud semantics over RESTfull HTTP API for connectors. Only read
+ * is supported as creation, update and delete might be done only directly on
+ * server side.
+ */
public class ConnectorRequest extends Request
{
- public ConnectorBean doGet(String serverUrl, String cid) {
+ public static final String RESOURCE = "v1/connector/";
+
+ public ConnectorBean read(String serverUrl, String cid) {
String response = null;
if (cid == null) {
- response = super.get(serverUrl + "v1/connector/all");
+ response = super.get(serverUrl + RESOURCE + "all");
} else {
- response = super.get(serverUrl + "v1/connector/" + cid);
+ response = super.get(serverUrl + RESOURCE + cid);
}
JSONObject jsonObject = (JSONObject)JSONValue.parse(response);
@@ -37,4 +44,4 @@ public class ConnectorRequest extends Request
return connectorBean;
}
-}
\ No newline at end of file
+}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/client/src/main/java/org/apache/sqoop/client/request/FrameworkRequest.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/sqoop/client/request/FrameworkRequest.java b/client/src/main/java/org/apache/sqoop/client/request/FrameworkRequest.java
index c9ae901..06f9006 100644
--- a/client/src/main/java/org/apache/sqoop/client/request/FrameworkRequest.java
+++ b/client/src/main/java/org/apache/sqoop/client/request/FrameworkRequest.java
@@ -22,12 +22,16 @@ import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
/**
- *
+ * Provide cRud semantics over RESTfull HTTP API for framework. Only read
+ * is supported as creation, update and delete is not allowed.
*/
public class FrameworkRequest extends Request {
- public FrameworkBean doGet(String serverUrl) {
+
+ public static final String RESOURCE = "v1/framework";
+
+ public FrameworkBean read(String serverUrl) {
String response = null;
- response = super.get(serverUrl + "v1/framework");
+ response = super.get(serverUrl + RESOURCE);
JSONObject jsonObject = (JSONObject) JSONValue.parse(response);
FrameworkBean frameworkBean = new FrameworkBean();
http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/client/src/main/java/org/apache/sqoop/client/request/Request.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/sqoop/client/request/Request.java b/client/src/main/java/org/apache/sqoop/client/request/Request.java
index bd3059d..5e381c9 100644
--- a/client/src/main/java/org/apache/sqoop/client/request/Request.java
+++ b/client/src/main/java/org/apache/sqoop/client/request/Request.java
@@ -20,21 +20,88 @@ package org.apache.sqoop.client.request;
import javax.ws.rs.core.MediaType;
import com.sun.jersey.api.client.Client;
+import com.sun.jersey.api.client.ClientRequest;
+import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.WebResource.Builder;
+import com.sun.jersey.api.client.filter.ClientFilter;
+import org.apache.sqoop.client.core.ClientError;
+import org.apache.sqoop.common.SqoopException;
+import org.apache.sqoop.common.SqoopProtocolConstants;
+import org.apache.sqoop.json.ExceptionInfo;
+import org.json.simple.JSONObject;
+import org.json.simple.JSONValue;
import java.util.Locale;
public class Request
{
- public String get(String url) {
+ private static ServerExceptionFilter serverExceptionFilter;
+
+ static {
+ serverExceptionFilter = new ServerExceptionFilter();
+ }
+
+ protected Builder getBuilder(String url) {
Client client = Client.create();
WebResource resource = client.resource(url);
- Builder builder = resource
+
+ // Provide filter that will rebuild exception that is sent from server
+ resource.addFilter(serverExceptionFilter);
+
+ return resource
// Sqoop is using JSON for data transfers
.accept(MediaType.APPLICATION_JSON_TYPE)
// Transfer client locale to return client specific data
.acceptLanguage(Locale.getDefault());
- return builder.get(String.class);
+ }
+
+ public String get(String url) {
+ return getBuilder(url).get(String.class);
+ }
+
+ public String post(String url, String data) {
+ return getBuilder(url).post(String.class, data);
+ }
+
+ public String put(String url, String data) {
+ return getBuilder(url).put(String.class, data);
+ }
+
+ public void delete(String url) {
+ getBuilder(url).delete(String.class);
+ }
+
+ /**
+ * Client filter to intercepting exceptions sent by sqoop server and
+ * recreating them on client side. Current implementation will create new
+ * instance of SqoopException and will attach original error code and message.
+ */
+ private static class ServerExceptionFilter extends ClientFilter {
+ @Override
+ public ClientResponse handle(ClientRequest cr) {
+ ClientResponse resp = getNext().handle(cr);
+
+ // Special handling for 500 internal server error in case that server
+ // has sent us it's exception correctly. We're using default route
+ // for all other 500 occurrences.
+ if(resp.getClientResponseStatus()
+ == ClientResponse.Status.INTERNAL_SERVER_ERROR) {
+
+ if(resp.getHeaders().containsKey(
+ SqoopProtocolConstants.HEADER_SQOOP_INTERNAL_ERROR_CODE)) {
+
+ ExceptionInfo ex = new ExceptionInfo();
+
+ String responseText = resp.getEntity(String.class);
+ JSONObject json = (JSONObject) JSONValue.parse(responseText);
+ ex.restore(json);
+
+ throw new SqoopException(ClientError.CLIENT_0006, ex.toString());
+ }
+ }
+
+ return resp;
+ }
}
}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/client/src/main/java/org/apache/sqoop/client/request/VersionRequest.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/sqoop/client/request/VersionRequest.java b/client/src/main/java/org/apache/sqoop/client/request/VersionRequest.java
index 511878c..2b236ba 100644
--- a/client/src/main/java/org/apache/sqoop/client/request/VersionRequest.java
+++ b/client/src/main/java/org/apache/sqoop/client/request/VersionRequest.java
@@ -32,4 +32,4 @@ public class VersionRequest extends Request
return versionBean;
}
-}
\ No newline at end of file
+}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/client/src/main/java/org/apache/sqoop/client/shell/CreateCommand.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/sqoop/client/shell/CreateCommand.java b/client/src/main/java/org/apache/sqoop/client/shell/CreateCommand.java
new file mode 100644
index 0000000..bf4b581
--- /dev/null
+++ b/client/src/main/java/org/apache/sqoop/client/shell/CreateCommand.java
@@ -0,0 +1,58 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sqoop.client.shell;
+
+import org.apache.sqoop.client.core.ClientError;
+import org.apache.sqoop.common.SqoopException;
+import org.codehaus.groovy.tools.shell.Shell;
+
+import java.util.List;
+
+/**
+ *
+ */
+public class CreateCommand extends SqoopCommand {
+
+ private CreateConnectionFunction connectionFunction;
+
+ public CreateCommand(Shell shell) {
+ super(shell, "create", "\\cr",
+ new String[] {"connection", "job"},
+ "Create", "info");
+ }
+
+ public Object execute(List args) {
+ if (args.size() == 0) {
+ io.out.println("Usage: create " + getUsage());
+ io.out.println();
+ return null;
+ }
+
+ String func = (String)args.get(0);
+ if (func.equals("connection")) {
+ if (connectionFunction == null) {
+ connectionFunction = new CreateConnectionFunction(io);
+ }
+ return connectionFunction.execute(args);
+
+ } else {
+ String msg = "Usage: create " + getUsage();
+ throw new SqoopException(ClientError.CLIENT_0002, msg);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/client/src/main/java/org/apache/sqoop/client/shell/CreateConnectionFunction.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/sqoop/client/shell/CreateConnectionFunction.java b/client/src/main/java/org/apache/sqoop/client/shell/CreateConnectionFunction.java
new file mode 100644
index 0000000..aef4b92
--- /dev/null
+++ b/client/src/main/java/org/apache/sqoop/client/shell/CreateConnectionFunction.java
@@ -0,0 +1,156 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sqoop.client.shell;
+
+import jline.ConsoleReader;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.OptionBuilder;
+import org.apache.sqoop.client.core.ClientError;
+import org.apache.sqoop.client.core.Environment;
+import org.apache.sqoop.client.request.ConnectionRequest;
+import org.apache.sqoop.client.request.ConnectorRequest;
+import org.apache.sqoop.client.request.FrameworkRequest;
+import org.apache.sqoop.common.SqoopException;
+import org.apache.sqoop.json.ConnectorBean;
+import org.apache.sqoop.json.FrameworkBean;
+import org.apache.sqoop.model.MConnection;
+import org.apache.sqoop.model.MConnector;
+import org.apache.sqoop.model.MFramework;
+import org.apache.sqoop.validation.Status;
+import org.codehaus.groovy.tools.shell.IO;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.ResourceBundle;
+
+import static org.apache.sqoop.client.utils.FormFiller.*;
+
+/**
+ *
+ */
+public class CreateConnectionFunction extends SqoopFunction {
+
+ private static final String CID = "cid";
+
+ private FrameworkRequest frameworkRequest;
+ private ConnectorRequest connectorRequest;
+ private ConnectionRequest connectionRequest;
+
+ private IO io;
+
+ @SuppressWarnings("static-access")
+ public CreateConnectionFunction(IO io) {
+ this.io = io;
+
+ this.addOption(OptionBuilder
+ .withDescription("Connector ID")
+ .withLongOpt(CID)
+ .hasArg()
+ .create(CID.charAt(0)));
+ }
+
+ public Object execute(List<String> args) {
+ CommandLine line = parseOptions(this, 1, args);
+ if (!line.hasOption(CID)) {
+ io.out.println("Required argument --cid is missing.");
+ return null;
+ }
+
+ try {
+ createConnection(line.getOptionValue(CID));
+ } catch (IOException ex) {
+ throw new SqoopException(ClientError.CLIENT_0005, ex);
+ }
+
+ return null;
+ }
+
+ private void createConnection(String connectorId) throws IOException {
+ io.out.println("Creating connection for connector with id " + connectorId);
+
+ ConsoleReader reader = new ConsoleReader();
+
+ FrameworkBean frameworkBean = getFrameworkBean();
+ ConnectorBean connectorBean = getConnectorBean(connectorId);
+
+ MFramework framework = frameworkBean.getFramework();
+ ResourceBundle frameworkBundle = frameworkBean.getResourceBundle();
+
+ MConnector connector = connectorBean.getConnectors().get(0);
+ ResourceBundle connectorBundle = connectorBean.getResourceBundles().get(0);
+
+ MConnection connection = new MConnection(connector.getPersistenceId(),
+ connector.getConnectionForms(),
+ framework.getConnectionForms());
+
+ Status status = Status.FINE;
+
+ io.out.println("Please fill following values to create new connection"
+ + " object");
+
+ do {
+ if( !status.canProceed() ) {
+ io.out.println();
+ io.out.println("@|red There are issues with entered data, please"
+ + " revise your input:|@");
+ }
+
+ // Query connector forms
+ if(!fillForms(io, connection.getConnectorPart(),
+ reader, connectorBundle)) {
+ return;
+ }
+
+ // Query framework forms
+ if(!fillForms(io, connection.getFrameworkPart(),
+ reader, frameworkBundle)) {
+ return;
+ }
+
+ // Try to create
+ status = createConnection(connection);
+ } while(!status.canProceed());
+
+ io.out.println("New connection was successfully created with validation "
+ + "status " + status.name());
+ }
+
+ private FrameworkBean getFrameworkBean() {
+ if (frameworkRequest == null) {
+ frameworkRequest = new FrameworkRequest();
+ }
+
+ return frameworkRequest.read(Environment.getServerUrl());
+ }
+
+ private ConnectorBean getConnectorBean(String cid) {
+ if (connectorRequest == null) {
+ connectorRequest = new ConnectorRequest();
+ }
+
+ return connectorRequest.read(Environment.getServerUrl(), cid);
+ }
+
+ private Status createConnection(MConnection connection) {
+ if (connectionRequest == null) {
+ connectionRequest = new ConnectionRequest();
+ }
+
+ return connectionRequest.create(Environment.getServerUrl(), connection);
+ }
+}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/client/src/main/java/org/apache/sqoop/client/shell/DeleteCommand.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/sqoop/client/shell/DeleteCommand.java b/client/src/main/java/org/apache/sqoop/client/shell/DeleteCommand.java
new file mode 100644
index 0000000..1616b4a
--- /dev/null
+++ b/client/src/main/java/org/apache/sqoop/client/shell/DeleteCommand.java
@@ -0,0 +1,58 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sqoop.client.shell;
+
+import org.apache.sqoop.client.core.ClientError;
+import org.apache.sqoop.common.SqoopException;
+import org.codehaus.groovy.tools.shell.Shell;
+
+import java.util.List;
+
+/**
+ *
+ */
+public class DeleteCommand extends SqoopCommand {
+
+ private DeleteConnectionFunction connectionFunction;
+
+ public DeleteCommand(Shell shell) {
+ super(shell, "delete", "\\d",
+ new String[] {"connection", "job"},
+ "Delete", "info");
+ }
+
+ @SuppressWarnings("unchecked")
+ public Object execute(List args) {
+ if (args.size() == 0) {
+ io.out.println("Usage: delete " + getUsage());
+ io.out.println();
+ return null;
+ }
+
+ String func = (String)args.get(0);
+ if (func.equals("connection")) {
+ if (connectionFunction == null) {
+ connectionFunction = new DeleteConnectionFunction(io);
+ }
+ return connectionFunction.execute(args);
+
+ } else {
+ String msg = "Usage: delete " + getUsage();
+ throw new SqoopException(ClientError.CLIENT_0002, msg);
+ } }
+}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/client/src/main/java/org/apache/sqoop/client/shell/DeleteConnectionFunction.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/sqoop/client/shell/DeleteConnectionFunction.java b/client/src/main/java/org/apache/sqoop/client/shell/DeleteConnectionFunction.java
new file mode 100644
index 0000000..43a4002
--- /dev/null
+++ b/client/src/main/java/org/apache/sqoop/client/shell/DeleteConnectionFunction.java
@@ -0,0 +1,67 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sqoop.client.shell;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.OptionBuilder;
+import org.apache.sqoop.client.core.Environment;
+import org.apache.sqoop.client.request.ConnectionRequest;
+import org.codehaus.groovy.tools.shell.IO;
+
+import java.util.List;
+
+/**
+ *
+ */
+public class DeleteConnectionFunction extends SqoopFunction {
+
+ private IO io;
+
+ private ConnectionRequest connectionRequest;
+
+ private static final String XID = "xid";
+
+ @SuppressWarnings("static-access")
+ public DeleteConnectionFunction(IO io) {
+ this.io = io;
+
+ this.addOption(OptionBuilder
+ .withDescription("Connection ID")
+ .withLongOpt(XID)
+ .hasArg()
+ .create('x'));
+ }
+
+ public Object execute(List<String> args) {
+ CommandLine line = parseOptions(this, 1, args);
+ if (!line.hasOption(XID)) {
+ io.out.println("Required argument --xid is missing.");
+ return null;
+ }
+
+ if (connectionRequest == null) {
+ connectionRequest = new ConnectionRequest();
+ }
+
+ connectionRequest.delete(Environment.getServerUrl(),
+ Long.valueOf(line.getOptionValue(XID)));
+
+ return null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/client/src/main/java/org/apache/sqoop/client/shell/ShowCommand.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/sqoop/client/shell/ShowCommand.java b/client/src/main/java/org/apache/sqoop/client/shell/ShowCommand.java
index 584d04b..22182e9 100644
--- a/client/src/main/java/org/apache/sqoop/client/shell/ShowCommand.java
+++ b/client/src/main/java/org/apache/sqoop/client/shell/ShowCommand.java
@@ -29,6 +29,7 @@ public class ShowCommand extends SqoopCommand
private ShowVersionFunction versionFunction;
private ShowConnectorFunction connectorFunction;
private ShowFrameworkFunction frameworkFunction;
+ private ShowConnectionFunction connectionFunction;
protected ShowCommand(Shell shell) {
super(shell, "show", "\\sh",
@@ -71,7 +72,10 @@ public class ShowCommand extends SqoopCommand
return frameworkFunction.execute(args);
} else if (func.equals("connection")) {
- return null;
+ if (connectionFunction == null) {
+ connectionFunction = new ShowConnectionFunction(io);
+ }
+ return connectionFunction.execute(args);
} else if (func.equals("job")) {
return null;
http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/client/src/main/java/org/apache/sqoop/client/shell/ShowConnectionFunction.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/sqoop/client/shell/ShowConnectionFunction.java b/client/src/main/java/org/apache/sqoop/client/shell/ShowConnectionFunction.java
new file mode 100644
index 0000000..a499ff8
--- /dev/null
+++ b/client/src/main/java/org/apache/sqoop/client/shell/ShowConnectionFunction.java
@@ -0,0 +1,107 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sqoop.client.shell;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.OptionBuilder;
+import org.apache.sqoop.client.core.Environment;
+import org.apache.sqoop.client.request.ConnectionRequest;
+import org.apache.sqoop.json.ConnectionBean;
+import org.apache.sqoop.model.MConnection;
+import org.codehaus.groovy.tools.shell.IO;
+
+import java.io.PrintWriter;
+import java.util.List;
+
+import static org.apache.sqoop.client.utils.FormDisplayer.*;
+
+/**
+ *
+ */
+public class ShowConnectionFunction extends SqoopFunction {
+ public static final String ALL = "all";
+ public static final String XID = "xid";
+
+ private IO io;
+ private ConnectionRequest connectionRequest;
+
+ @SuppressWarnings("static-access")
+ protected ShowConnectionFunction(IO io) {
+ this.io = io;
+
+ this.addOption(OptionBuilder
+ .withDescription("Display all connections")
+ .withLongOpt(ALL)
+ .create(ALL.charAt(0)));
+ this.addOption(OptionBuilder.hasArg().withArgName("xid")
+ .withDescription( "Display the connection with xid" )
+ .withLongOpt(XID)
+ .create('x'));
+ }
+
+ public void printHelp(PrintWriter out) {
+ out.println("Usage: show connection");
+ super.printHelp(out);
+ }
+
+ public Object execute(List<String> args) {
+ if (args.size() == 1) {
+ printHelp(io.out);
+ io.out.println();
+ return null;
+ }
+
+ CommandLine line = parseOptions(this, 1, args);
+ if (line.hasOption(ALL)) {
+ showConnection(null);
+
+ } else if (line.hasOption(XID)) {
+ showConnection(line.getOptionValue(XID));
+ }
+
+ return null;
+ }
+
+ private void showConnection(String xid) {
+ if (connectionRequest == null) {
+ connectionRequest = new ConnectionRequest();
+ }
+ ConnectionBean connectionBean =
+ connectionRequest.read(Environment.getServerUrl(), xid);
+
+ List<MConnection> connections = connectionBean.getConnections();
+
+ io.out.println("@|bold " + connections.size()
+ + " connection(s) to show: |@");
+
+ for (MConnection connection : connections) {
+ io.out.println("Connection with id " + connection.getPersistenceId()
+ + " and name: " + connection.getName());
+
+ long connectorId = connection.getConnectorId();
+
+ // Display connector part
+ displayForms(io,
+ connection.getConnectorPart().getForms(),
+ connectionBean.getConnectorBundle(connectorId));
+ displayForms(io,
+ connection.getFrameworkPart().getForms(),
+ connectionBean.getFrameworkBundle());
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/client/src/main/java/org/apache/sqoop/client/shell/ShowConnectorFunction.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/sqoop/client/shell/ShowConnectorFunction.java b/client/src/main/java/org/apache/sqoop/client/shell/ShowConnectorFunction.java
index 140c78a..07c9c56 100644
--- a/client/src/main/java/org/apache/sqoop/client/shell/ShowConnectorFunction.java
+++ b/client/src/main/java/org/apache/sqoop/client/shell/ShowConnectorFunction.java
@@ -19,6 +19,7 @@ package org.apache.sqoop.client.shell;
import java.io.PrintWriter;
import java.util.List;
+import java.util.ResourceBundle;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.OptionBuilder;
@@ -26,10 +27,9 @@ import org.apache.sqoop.client.core.Environment;
import org.apache.sqoop.client.request.ConnectorRequest;
import org.apache.sqoop.json.ConnectorBean;
import org.apache.sqoop.model.MConnector;
-import org.apache.sqoop.model.MJobForms;
import org.codehaus.groovy.tools.shell.IO;
-import static org.apache.sqoop.client.display.FormDisplayer.*;
+import static org.apache.sqoop.client.utils.FormDisplayer.*;
@SuppressWarnings("serial")
public class ShowConnectorFunction extends SqoopFunction
@@ -82,12 +82,13 @@ public class ShowConnectorFunction extends SqoopFunction
conntectorRequest = new ConnectorRequest();
}
ConnectorBean connectorBean =
- conntectorRequest.doGet(Environment.getServerUrl(), cid);
- MConnector[] connectors = connectorBean.getConnectors();
+ conntectorRequest.read(Environment.getServerUrl(), cid);
+ List<MConnector> connectors = connectorBean.getConnectors();
+ List<ResourceBundle> bundles = connectorBean.getResourceBundles();
- io.out.println("@|bold " + connectors.length + " connector(s) to show: |@");
- for (int i = 0; i < connectors.length; i++) {
- MConnector connector = connectors[i];
+ io.out.println("@|bold " + connectors.size() + " connector(s) to show: |@");
+ for (int i = 0; i < connectors.size(); i++) {
+ MConnector connector = connectors.get(i);
io.out.print("Connector with id ");
io.out.print(connector.getPersistenceId());
@@ -98,7 +99,7 @@ public class ShowConnectorFunction extends SqoopFunction
io.out.print(" Class: ");
io.out.println(connector.getClassName());
- displayFormDetails(io, connector);
+ displayFormMetadataDetails(io, connector, bundles.get(i));
}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/client/src/main/java/org/apache/sqoop/client/shell/ShowFrameworkFunction.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/sqoop/client/shell/ShowFrameworkFunction.java b/client/src/main/java/org/apache/sqoop/client/shell/ShowFrameworkFunction.java
index bcb267e..532ff04 100644
--- a/client/src/main/java/org/apache/sqoop/client/shell/ShowFrameworkFunction.java
+++ b/client/src/main/java/org/apache/sqoop/client/shell/ShowFrameworkFunction.java
@@ -21,13 +21,13 @@ import org.apache.sqoop.client.core.Environment;
import org.apache.sqoop.client.request.FrameworkRequest;
import org.apache.sqoop.json.FrameworkBean;
import org.apache.sqoop.model.MFramework;
-import org.apache.sqoop.model.MJobForms;
import org.codehaus.groovy.tools.shell.IO;
import java.io.PrintWriter;
import java.util.List;
+import java.util.ResourceBundle;
-import static org.apache.sqoop.client.display.FormDisplayer.*;
+import static org.apache.sqoop.client.utils.FormDisplayer.*;
/**
*
@@ -65,15 +65,17 @@ public class ShowFrameworkFunction extends SqoopFunction {
}
FrameworkBean frameworkBean =
- frameworkRequest.doGet(Environment.getServerUrl());
+ frameworkRequest.read(Environment.getServerUrl());
+
MFramework framework = frameworkBean.getFramework();
+ ResourceBundle bundle = frameworkBean.getResourceBundle();
io.out.println("@|bold Framework specific options: |@");
io.out.print("Persistent id: ");
io.out.println(framework.getPersistenceId());
- displayFormDetails(io, framework);
+ displayFormMetadataDetails(io, framework, bundle);
io.out.println();
}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/client/src/main/java/org/apache/sqoop/client/shell/SqoopShell.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/sqoop/client/shell/SqoopShell.java b/client/src/main/java/org/apache/sqoop/client/shell/SqoopShell.java
index acf1222..91682d1 100644
--- a/client/src/main/java/org/apache/sqoop/client/shell/SqoopShell.java
+++ b/client/src/main/java/org/apache/sqoop/client/shell/SqoopShell.java
@@ -32,13 +32,13 @@ public class SqoopShell
{
private static final String banner =
"@|green Sqoop Shell:|@ Type '@|bold help|@' or '@|bold \\h|@' for help.";
-
+
public static HashSet<String> commandsToKeep;
static {
commandsToKeep = new HashSet<String>();
commandsToKeep.add("exit");
commandsToKeep.add("history");
- };
+ }
public static void main (String[] args) throws Exception
{
@@ -60,6 +60,9 @@ public class SqoopShell
shell.register(new HelpCommand(shell));
shell.register(new SetCommand(shell));
shell.register(new ShowCommand(shell));
+ shell.register(new CreateCommand(shell));
+ shell.register(new DeleteCommand(shell));
+ shell.register(new UpdateCommand(shell));
if (args.length == 0) {
// Interactive mode:
@@ -88,4 +91,4 @@ public class SqoopShell
}
}
}
-}
\ No newline at end of file
+}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/client/src/main/java/org/apache/sqoop/client/shell/UpdateCommand.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/sqoop/client/shell/UpdateCommand.java b/client/src/main/java/org/apache/sqoop/client/shell/UpdateCommand.java
new file mode 100644
index 0000000..ad72a4e
--- /dev/null
+++ b/client/src/main/java/org/apache/sqoop/client/shell/UpdateCommand.java
@@ -0,0 +1,58 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sqoop.client.shell;
+
+import org.apache.sqoop.client.core.ClientError;
+import org.apache.sqoop.common.SqoopException;
+import org.codehaus.groovy.tools.shell.Shell;
+
+import java.util.List;
+
+/**
+ *
+ */
+public class UpdateCommand extends SqoopCommand {
+
+ private UpdateConnectionFunction connectionFunction;
+
+ public UpdateCommand(Shell shell) {
+ super(shell, "update", "\\up",
+ new String[] {"connection", "job"},
+ "Update", "info");
+ }
+
+ public Object execute(List args) {
+ if (args.size() == 0) {
+ io.out.println("Usage: create " + getUsage());
+ io.out.println();
+ return null;
+ }
+
+ String func = (String)args.get(0);
+ if (func.equals("connection")) {
+ if (connectionFunction == null) {
+ connectionFunction = new UpdateConnectionFunction(io);
+ }
+ return connectionFunction.execute(args);
+
+ } else {
+ String msg = "Usage: update " + getUsage();
+ throw new SqoopException(ClientError.CLIENT_0002, msg);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/client/src/main/java/org/apache/sqoop/client/shell/UpdateConnectionFunction.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/sqoop/client/shell/UpdateConnectionFunction.java b/client/src/main/java/org/apache/sqoop/client/shell/UpdateConnectionFunction.java
new file mode 100644
index 0000000..c9ced51
--- /dev/null
+++ b/client/src/main/java/org/apache/sqoop/client/shell/UpdateConnectionFunction.java
@@ -0,0 +1,136 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sqoop.client.shell;
+
+import jline.ConsoleReader;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.OptionBuilder;
+import org.apache.sqoop.client.core.ClientError;
+import org.apache.sqoop.client.core.Environment;
+import org.apache.sqoop.client.request.ConnectionRequest;
+import org.apache.sqoop.common.SqoopException;
+import org.apache.sqoop.json.ConnectionBean;
+import org.apache.sqoop.model.MConnection;
+import org.apache.sqoop.validation.Status;
+import org.codehaus.groovy.tools.shell.IO;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.ResourceBundle;
+
+import static org.apache.sqoop.client.utils.FormFiller.*;
+
+/**
+ *
+ */
+public class UpdateConnectionFunction extends SqoopFunction {
+
+ private static final String XID = "xid";
+
+ private ConnectionRequest connectionRequest;
+
+ private IO io;
+
+ @SuppressWarnings("static-access")
+ public UpdateConnectionFunction(IO io) {
+ this.io = io;
+
+ this.addOption(OptionBuilder
+ .withDescription("Connection ID")
+ .withLongOpt(XID)
+ .hasArg()
+ .create(XID.charAt(0)));
+ }
+
+ public Object execute(List<String> args) {
+ CommandLine line = parseOptions(this, 1, args);
+ if (!line.hasOption(XID)) {
+ io.out.println("Required argument --xid is missing.");
+ return null;
+ }
+
+ try {
+ updateConnection(line.getOptionValue(XID));
+ } catch (IOException ex) {
+ throw new SqoopException(ClientError.CLIENT_0005, ex);
+ }
+
+ return null;
+ }
+
+ private void updateConnection(String connectionId) throws IOException {
+ io.out.println("Updating connection with id " + connectionId);
+
+ ConsoleReader reader = new ConsoleReader();
+
+ ConnectionBean connectionBean = readConnection(connectionId);
+
+ // TODO(jarcec): Check that we have expected data
+ MConnection connection = connectionBean.getConnections().get(0);
+ ResourceBundle frameworkBundle
+ = connectionBean.getFrameworkBundle();
+ ResourceBundle connectorBundle
+ = connectionBean.getConnectorBundle(connection.getConnectorId());
+
+ Status status = Status.FINE;
+
+ io.out.println("Please update connection metadata:");
+
+ do {
+ if( !status.canProceed() ) {
+ io.out.println();
+ io.out.println("@|red There are issues with entered data, please"
+ + " revise your input:|@");
+ }
+
+ // Query connector forms
+ if(!fillForms(io, connection.getConnectorPart(),
+ reader, connectorBundle)) {
+ return;
+ }
+
+ // Query framework forms
+ if(!fillForms(io, connection.getFrameworkPart(),
+ reader, frameworkBundle)) {
+ return;
+ }
+
+ // Try to create
+ status = updateConnection(connection);
+ } while(!status.canProceed());
+
+ io.out.println("Connection was sucessfully updated with status "
+ + status.name());
+ }
+
+ private Status updateConnection(MConnection connection) {
+ if (connectionRequest == null) {
+ connectionRequest = new ConnectionRequest();
+ }
+
+ return connectionRequest.update(Environment.getServerUrl(), connection);
+ }
+
+ private ConnectionBean readConnection(String connectionId) {
+ if (connectionRequest == null) {
+ connectionRequest = new ConnectionRequest();
+ }
+
+ return connectionRequest.read(Environment.getServerUrl(), connectionId);
+ }
+}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/client/src/main/java/org/apache/sqoop/client/utils/FormDisplayer.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/sqoop/client/utils/FormDisplayer.java b/client/src/main/java/org/apache/sqoop/client/utils/FormDisplayer.java
new file mode 100644
index 0000000..02588c7
--- /dev/null
+++ b/client/src/main/java/org/apache/sqoop/client/utils/FormDisplayer.java
@@ -0,0 +1,135 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sqoop.client.utils;
+
+import org.apache.sqoop.model.MForm;
+import org.apache.sqoop.model.MFramework;
+import org.apache.sqoop.model.MInput;
+import org.apache.sqoop.model.MInputType;
+import org.apache.sqoop.model.MJobForms;
+import org.apache.sqoop.model.MStringInput;
+import org.codehaus.groovy.tools.shell.IO;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.ResourceBundle;
+
+/**
+ * Convenience static methods for displaying form related information
+ */
+public class FormDisplayer {
+
+ public static void displayFormMetadataDetails(IO io,
+ MFramework framework,
+ ResourceBundle bundle) {
+ io.out.print(" Supported job types: ");
+ io.out.println(framework.getAllJobsForms().keySet().toString());
+
+ displayFormsMetadata(io,
+ framework.getConnectionForms().getForms(),
+ "Connection",
+ bundle);
+
+ for (MJobForms jobForms : framework.getAllJobsForms().values()) {
+ io.out.print(" Forms for job type ");
+ io.out.print(jobForms.getType().name());
+ io.out.println(":");
+
+ displayFormsMetadata(io, jobForms.getForms(), "Job", bundle);
+ }
+ }
+
+ public static void displayFormsMetadata(IO io,
+ List<MForm> forms,
+ String type,
+ ResourceBundle bundle) {
+ Iterator<MForm> fiter = forms.iterator();
+ int findx = 1;
+ while (fiter.hasNext()) {
+ io.out.print(" ");
+ io.out.print(type);
+ io.out.print(" form ");
+ io.out.print(findx++);
+ io.out.println(":");
+
+ MForm form = fiter.next();
+ io.out.print(" Name: ");
+ io.out.println(form.getName());
+
+ // Label
+ io.out.print(" Label: ");
+ io.out.println(bundle.getString(form.getLabelKey()));
+
+ // Help text
+ io.out.print(" Help: ");
+ io.out.println(bundle.getString(form.getHelpKey()));
+
+ List<MInput<?>> inputs = form.getInputs();
+ Iterator<MInput<?>> iiter = inputs.iterator();
+ int iindx = 1;
+ while (iiter.hasNext()) {
+ io.out.print(" Input ");
+ io.out.print(iindx++);
+ io.out.println(":");
+
+ MInput<?> input = iiter.next();
+ io.out.print(" Name: ");
+ io.out.println(input.getName());
+ io.out.print(" Label: ");
+ io.out.println(bundle.getString(input.getLabelKey()));
+ io.out.print(" Help: ");
+ io.out.println(bundle.getString(input.getHelpKey()));
+ io.out.print(" Type: ");
+ io.out.println(input.getType());
+ if (input.getType() == MInputType.STRING) {
+ io.out.print(" Mask: ");
+ io.out.println(((MStringInput)input).isMasked());
+ io.out.print(" Size: ");
+ io.out.println(((MStringInput)input).getMaxLength());
+ }
+ }
+ }
+ }
+
+ public static void displayForms(IO io,
+ List<MForm> forms,
+ ResourceBundle bundle) {
+ for(MForm form : forms) {
+ displayForm(io, form, bundle);
+ }
+ }
+
+ private static void displayForm(IO io, MForm form, ResourceBundle bundle) {
+ io.out.print(" ");
+ io.out.println(bundle.getString(form.getLabelKey()));
+
+ for (MInput<?> input : form.getInputs()) {
+ io.out.print(" ");
+ io.out.print(bundle.getString(input.getLabelKey()));
+ io.out.print(": ");
+ if(!input.isEmpty()) {
+ io.out.print(input.getUrlSafeValueString());
+ }
+ io.out.println("");
+ }
+ }
+
+ private FormDisplayer() {
+ // Do not instantiate
+ }
+}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/client/src/main/java/org/apache/sqoop/client/utils/FormFiller.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/sqoop/client/utils/FormFiller.java b/client/src/main/java/org/apache/sqoop/client/utils/FormFiller.java
new file mode 100644
index 0000000..5b6ebb9
--- /dev/null
+++ b/client/src/main/java/org/apache/sqoop/client/utils/FormFiller.java
@@ -0,0 +1,132 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sqoop.client.utils;
+
+import jline.ConsoleReader;
+import org.apache.sqoop.model.MConnectionForms;
+import org.apache.sqoop.model.MForm;
+import org.apache.sqoop.model.MInput;
+import org.apache.sqoop.model.MStringInput;
+import org.codehaus.groovy.tools.shell.IO;
+
+import java.io.IOException;
+import java.util.ResourceBundle;
+
+/**
+ *
+ */
+public class FormFiller {
+
+
+ public static boolean fillForms(IO io,
+ MConnectionForms formsMetadata,
+ ConsoleReader reader,
+ ResourceBundle bundle)
+ throws IOException {
+ for (MForm form : formsMetadata.getForms()) {
+ if(!fillForm(io, form, reader, bundle)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public static boolean fillForm(IO io,
+ MForm form,
+ ConsoleReader reader,
+ ResourceBundle bundle) throws IOException {
+ io.out.println("");
+ io.out.println(bundle.getString(form.getLabelKey()));
+ for (MInput input : form.getInputs()) {
+ if(!fillInput(io, input, reader, bundle)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public static boolean fillInput(IO io,
+ MInput input,
+ ConsoleReader reader,
+ ResourceBundle bundle) throws IOException {
+ // Print out warning or error message in case some validations were already
+ // performed.
+ switch (input.getValidationSeverity()) {
+ case ERROR:
+ io.out.println("Error message: @|red "
+ + input.getValidationMessage() + " |@");
+ break;
+ case WARNING:
+ io.out.println("Warning message: @|yellow "
+ + input.getValidationMessage() + " |@");
+ break;
+ default:
+ // Simply ignore all other states for the moment
+ break;
+ }
+
+ // Based on the input type, let's perform specific load
+ switch (input.getType()) {
+ case STRING:
+ return fillInputString(io, (MStringInput) input, reader, bundle);
+ //TODO(jarcec): Support MAP
+ default:
+ io.out.println("Unsupported data type " + input.getType());
+ return true;
+ }
+ }
+
+ public static boolean fillInputString(IO io,
+ MStringInput input,
+ ConsoleReader reader,
+ ResourceBundle bundle)
+ throws IOException {
+ // Print prompt
+ reader.printString(bundle.getString(input.getLabelKey()) + ": ");
+ reader.flushConsole();
+
+ // Fill already filled data when available
+ if(!input.isEmpty()) {
+ reader.putString(input.getValue());
+ }
+
+ // Get the data
+ String userTyped;
+ if(input.isMasked()) {
+ userTyped = reader.readLine('*');
+ } else {
+ userTyped = reader.readLine();
+ }
+
+ if (userTyped == null) {
+ return false;
+ } else if (userTyped.isEmpty()) {
+ input.setEmpty();
+ } else {
+ input.setValue(userTyped);
+ }
+
+ return true;
+ }
+
+ private FormFiller() {
+ // Do not instantiate
+ }
+}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/common/src/main/java/org/apache/sqoop/common/ExceptionInfo.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/common/ExceptionInfo.java b/common/src/main/java/org/apache/sqoop/common/ExceptionInfo.java
deleted file mode 100644
index b55111f..0000000
--- a/common/src/main/java/org/apache/sqoop/common/ExceptionInfo.java
+++ /dev/null
@@ -1,64 +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.common;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-
-import org.apache.sqoop.json.JsonBean;
-import org.json.simple.JSONObject;
-
-public class ExceptionInfo implements JsonBean {
-
- public static final String ERROR_CODE = "error-code";
- public static final String ERROR_MESSAGE = "error-message";
- public static final String STACK_TRACE = "stack-trace";
-
- private String errorCode;
- private String errorMessage;
- private String stackTrace;
-
- public ExceptionInfo(String code, String message, Exception ex) {
- errorCode = code;
- errorMessage = message;
-
- StringWriter writer = new StringWriter();
- ex.printStackTrace(new PrintWriter(writer));
- writer.flush();
-
- stackTrace = writer.getBuffer().toString();
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public JSONObject extract() {
- JSONObject result = new JSONObject();
- result.put(ERROR_CODE, errorCode);
- result.put(ERROR_MESSAGE, errorMessage);
- result.put(STACK_TRACE, stackTrace);
-
- return result;
- }
-
- @Override
- public void restore(JSONObject jsonObject) {
- errorCode = (String) jsonObject.get(ERROR_CODE);
- errorMessage = (String) jsonObject.get(ERROR_MESSAGE);
- stackTrace = (String) jsonObject.get(STACK_TRACE);
- }
-}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/common/src/main/java/org/apache/sqoop/json/ConnectionBean.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/json/ConnectionBean.java b/common/src/main/java/org/apache/sqoop/json/ConnectionBean.java
new file mode 100644
index 0000000..c793465
--- /dev/null
+++ b/common/src/main/java/org/apache/sqoop/json/ConnectionBean.java
@@ -0,0 +1,177 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sqoop.json;
+
+import org.apache.sqoop.model.MConnection;
+import org.apache.sqoop.model.MConnectionForms;
+import org.apache.sqoop.model.MForm;
+import org.json.simple.JSONArray;
+import org.json.simple.JSONObject;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.ResourceBundle;
+import java.util.Set;
+
+import static org.apache.sqoop.json.util.FormSerialization.*;
+import static org.apache.sqoop.json.util.ResourceBundleSerialization.*;
+
+/**
+ * Connection representation that is being send across the network between
+ * Sqoop server and client. Server might optionally send resource bundles
+ * associated with the connections to spare client of sending another HTTP
+ * requests to obtain them.
+ */
+public class ConnectionBean implements JsonBean {
+
+ private static final String ALL = "all";
+ private static final String ID = "id";
+ private static final String NAME = "name";
+ private static final String CONNECTOR_ID = "connector-id";
+ private static final String CONNECTOR_PART = "connector";
+ private static final String FRAMEWORK_PART = "framework";
+
+ // Compulsory
+ private List<MConnection> connections;
+
+ // Optional
+ private Map<Long, ResourceBundle> connectorBundles;
+ private ResourceBundle frameworkBundle;
+
+ // For "extract"
+ public ConnectionBean(MConnection connection) {
+ this();
+ this.connections = new ArrayList<MConnection>();
+ this.connections.add(connection);
+ }
+
+ public ConnectionBean(List<MConnection> connections) {
+ this();
+ this.connections = connections;
+ }
+
+ // For "restore"
+ public ConnectionBean() {
+ connectorBundles = new HashMap<Long, ResourceBundle>();
+ }
+
+ public void setFrameworkBundle(ResourceBundle frameworkBundle) {
+ this.frameworkBundle = frameworkBundle;
+ }
+
+ public void addConnectorBundle(Long id, ResourceBundle connectorBundle) {
+ connectorBundles.put(id, connectorBundle);
+ }
+
+ public boolean hasConnectorBundle(Long id) {
+ return connectorBundles.containsKey(id);
+ }
+
+ public List<MConnection> getConnections() {
+ return connections;
+ }
+
+ public ResourceBundle getConnectorBundle(Long id) {
+ return connectorBundles.get(id);
+ }
+
+ public ResourceBundle getFrameworkBundle() {
+ return frameworkBundle;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public JSONObject extract() {
+ JSONArray array = new JSONArray();
+
+ for(MConnection connection : connections) {
+ JSONObject object = new JSONObject();
+
+ object.put(ID, connection.getPersistenceId());
+ object.put(NAME, connection.getName());
+ object.put(CONNECTOR_ID, connection.getConnectorId());
+ object.put(CONNECTOR_PART,
+ extractForms(connection.getConnectorPart().getForms()));
+ object.put(FRAMEWORK_PART,
+ extractForms(connection.getFrameworkPart().getForms()));
+
+ array.add(object);
+ }
+
+ JSONObject all = new JSONObject();
+ all.put(ALL, array);
+
+ if(!connectorBundles.isEmpty()) {
+ JSONObject bundles = new JSONObject();
+
+ for(Map.Entry<Long, ResourceBundle> entry : connectorBundles.entrySet()) {
+ bundles.put(entry.getKey().toString(),
+ extractResourceBundle(entry.getValue()));
+ }
+
+ all.put(CONNECTOR_RESOURCES, bundles);
+ }
+ if(frameworkBundle != null) {
+ all.put(FRAMEWORK_RESOURCES,extractResourceBundle(frameworkBundle));
+ }
+ return all;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public void restore(JSONObject jsonObject) {
+ connections = new ArrayList<MConnection>();
+
+ JSONArray array = (JSONArray) jsonObject.get(ALL);
+
+ for (Object obj : array) {
+ JSONObject object = (JSONObject) obj;
+
+ long connectorId = (Long) object.get(CONNECTOR_ID);
+ JSONArray connectorPart = (JSONArray) object.get(CONNECTOR_PART);
+ JSONArray frameworkPart = (JSONArray) object.get(FRAMEWORK_PART);
+
+ List<MForm> connectorForms = restoreForms(connectorPart);
+ List<MForm> frameworkForms = restoreForms(frameworkPart);
+
+ MConnection connection = new MConnection(connectorId,
+ new MConnectionForms(connectorForms),
+ new MConnectionForms(frameworkForms));
+
+ connection.setPersistenceId((Long) object.get(ID));
+ connection.setName((String) object.get(NAME));
+
+ connections.add(connection);
+ }
+
+ if(jsonObject.containsKey(CONNECTOR_RESOURCES)) {
+ JSONObject bundles = (JSONObject) jsonObject.get(CONNECTOR_RESOURCES);
+ Set<Map.Entry<String, JSONObject>> entrySet = bundles.entrySet();
+ for (Map.Entry<String, JSONObject> entry : entrySet) {
+ connectorBundles.put(Long.parseLong(entry.getKey()),
+ restoreResourceBundle(entry.getValue()));
+ }
+ }
+ if(jsonObject.containsKey(FRAMEWORK_RESOURCES)) {
+ frameworkBundle = restoreResourceBundle(
+ (JSONObject) jsonObject.get(FRAMEWORK_RESOURCES));
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/common/src/main/java/org/apache/sqoop/json/ConnectorBean.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/json/ConnectorBean.java b/common/src/main/java/org/apache/sqoop/json/ConnectorBean.java
index 3bad175..f630f75 100644
--- a/common/src/main/java/org/apache/sqoop/json/ConnectorBean.java
+++ b/common/src/main/java/org/apache/sqoop/json/ConnectorBean.java
@@ -18,8 +18,10 @@
package org.apache.sqoop.json;
import java.util.ArrayList;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.ResourceBundle;
import java.util.Set;
import org.apache.sqoop.model.MConnectionForms;
@@ -31,25 +33,33 @@ import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import static org.apache.sqoop.json.util.FormSerialization.*;
+import static org.apache.sqoop.json.util.ResourceBundleSerialization.*;
public class ConnectorBean implements JsonBean {
- private MConnector[] connectors;
+ private List<MConnector> connectors;
+
+ private List<ResourceBundle> bundles;
// for "extract"
- public ConnectorBean(MConnector[] connectors) {
- this.connectors = new MConnector[connectors.length];
- System.arraycopy(connectors, 0, this.connectors, 0, connectors.length);
+ public ConnectorBean(List<MConnector> connectors,
+ List<ResourceBundle> bundles) {
+ this.connectors = connectors;
+ this.bundles = bundles;
}
// for "restore"
public ConnectorBean() {
}
- public MConnector[] getConnectors() {
+ public List<MConnector> getConnectors() {
return connectors;
}
+ public List<ResourceBundle> getResourceBundles() {
+ return bundles;
+ }
+
@SuppressWarnings("unchecked")
@Override
public JSONObject extract() {
@@ -58,6 +68,7 @@ public class ConnectorBean implements JsonBean {
JSONArray classArray = new JSONArray();
JSONArray conFormsArray = new JSONArray();
JSONArray jobFormsArray = new JSONArray();
+ JSONArray bundlesArray;
for (MConnector connector : connectors) {
idArray.add(connector.getPersistenceId());
@@ -72,12 +83,15 @@ public class ConnectorBean implements JsonBean {
jobFormsArray.add(jobForms);
}
+ bundlesArray = extractResourceBundles(bundles);
+
JSONObject result = new JSONObject();
result.put(ID, idArray);
result.put(NAME, nameArray);
result.put(CLASS, classArray);
result.put(CON_FORMS, conFormsArray);
result.put(JOB_FORMS, jobFormsArray);
+ result.put(RESOURCES, bundlesArray);
return result;
}
@@ -92,8 +106,8 @@ public class ConnectorBean implements JsonBean {
JSONArray jobFormsArray =
(JSONArray) jsonObject.get(JOB_FORMS);
- connectors = new MConnector[idArray.size()];
- for (int i = 0; i < connectors.length; i++) {
+ connectors = new LinkedList<MConnector>();
+ for (int i = 0; i < idArray.size(); i++) {
long persistenceId = (Long) idArray.get(i);
String uniqueName = (String) nameArray.get(i);
String className = (String) classArray.get(i);
@@ -116,7 +130,9 @@ public class ConnectorBean implements JsonBean {
MConnector connector = new MConnector(uniqueName, className,
new MConnectionForms(connForms), jobs);
connector.setPersistenceId(persistenceId);
- connectors[i] = connector;
+ connectors.add(connector);
}
+
+ bundles = restoreResourceBundles((JSONArray) jsonObject.get(RESOURCES));
}
}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/common/src/main/java/org/apache/sqoop/json/ExceptionInfo.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/json/ExceptionInfo.java b/common/src/main/java/org/apache/sqoop/json/ExceptionInfo.java
new file mode 100644
index 0000000..68de4b1
--- /dev/null
+++ b/common/src/main/java/org/apache/sqoop/json/ExceptionInfo.java
@@ -0,0 +1,73 @@
+/**
+ * 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 java.io.PrintWriter;
+import java.io.StringWriter;
+
+import org.json.simple.JSONObject;
+
+public class ExceptionInfo implements JsonBean {
+
+ public static final String ERROR_CODE = "error-code";
+ public static final String ERROR_MESSAGE = "error-message";
+ public static final String STACK_TRACE = "stack-trace";
+
+ private String errorCode;
+ private String errorMessage;
+ private String stackTrace;
+
+ // For "extract"
+ public ExceptionInfo(String code, String message, Exception ex) {
+ errorCode = code;
+ errorMessage = message;
+
+ StringWriter writer = new StringWriter();
+ ex.printStackTrace(new PrintWriter(writer));
+ writer.flush();
+
+ stackTrace = writer.getBuffer().toString();
+ }
+
+ // For "restore"
+ public ExceptionInfo() {
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public JSONObject extract() {
+ JSONObject result = new JSONObject();
+ result.put(ERROR_CODE, errorCode);
+ result.put(ERROR_MESSAGE, errorMessage);
+ result.put(STACK_TRACE, stackTrace);
+
+ return result;
+ }
+
+ @Override
+ public void restore(JSONObject jsonObject) {
+ errorCode = (String) jsonObject.get(ERROR_CODE);
+ errorMessage = (String) jsonObject.get(ERROR_MESSAGE);
+ stackTrace = (String) jsonObject.get(STACK_TRACE);
+ }
+
+ @Override
+ public String toString() {
+ return errorMessage;
+ }
+}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/common/src/main/java/org/apache/sqoop/json/FrameworkBean.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/json/FrameworkBean.java b/common/src/main/java/org/apache/sqoop/json/FrameworkBean.java
index 47295e0..4e07b6c 100644
--- a/common/src/main/java/org/apache/sqoop/json/FrameworkBean.java
+++ b/common/src/main/java/org/apache/sqoop/json/FrameworkBean.java
@@ -28,9 +28,11 @@ import org.json.simple.JSONObject;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
+import java.util.ResourceBundle;
import java.util.Set;
import static org.apache.sqoop.json.util.FormSerialization.*;
+import static org.apache.sqoop.json.util.ResourceBundleSerialization.*;
/**
*
@@ -40,9 +42,12 @@ public class FrameworkBean implements JsonBean {
private MFramework framework;
+ private ResourceBundle bundle;
+
// for "extract"
- public FrameworkBean(MFramework framework) {
+ public FrameworkBean(MFramework framework, ResourceBundle bundle) {
this.framework = framework;
+ this.bundle = bundle;
}
// for "restore"
@@ -53,6 +58,10 @@ public class FrameworkBean implements JsonBean {
return framework;
}
+ public ResourceBundle getResourceBundle() {
+ return bundle;
+ }
+
@SuppressWarnings("unchecked")
@Override
public JSONObject extract() {
@@ -68,10 +77,10 @@ public class FrameworkBean implements JsonBean {
result.put(ID, framework.getPersistenceId());
result.put(CON_FORMS, conForms);
result.put(JOB_FORMS, jobForms);
+ result.put(RESOURCES, extractResourceBundle(bundle));
return result;
}
-
@Override
@SuppressWarnings("unchecked")
public void restore(JSONObject jsonObject) {
@@ -94,6 +103,8 @@ public class FrameworkBean implements JsonBean {
framework = new MFramework(new MConnectionForms(connForms), jobs);
framework.setPersistenceId(id);
+
+ bundle = restoreResourceBundle((JSONObject) jsonObject.get(RESOURCES));
}
}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/common/src/main/java/org/apache/sqoop/json/ValidationBean.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/sqoop/json/ValidationBean.java b/common/src/main/java/org/apache/sqoop/json/ValidationBean.java
new file mode 100644
index 0000000..73b73fa
--- /dev/null
+++ b/common/src/main/java/org/apache/sqoop/json/ValidationBean.java
@@ -0,0 +1,143 @@
+/**
+ * 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.MForm;
+import org.apache.sqoop.model.MInput;
+import org.apache.sqoop.model.MValidatedElement;
+import org.apache.sqoop.validation.Status;
+import org.json.simple.JSONObject;
+
+import java.util.List;
+
+/**
+ * Bean for sending validations across network. As is expected that both filled
+ * forms will be available on both ends (client and server), we're transferring
+ * only validation status and messages.
+ */
+public class ValidationBean implements JsonBean {
+
+ private static final String STATUS = "status";
+ private static final String CONNECTOR_PART = "connector";
+ private static final String FRAMEWORK_PART = "framework";
+
+ private static final String SEVERITY = "severity";
+ private static final String MESSAGE = "message";
+
+ private MConnection connection;
+ private Status status;
+
+ // For "extract"
+ public ValidationBean(MConnection connection, Status status) {
+ this.connection = connection;
+ this.status = status;
+ }
+
+ // For "restore"
+ public ValidationBean(MConnection connection) {
+ this.connection = connection;
+ }
+
+ public MConnection getConnection() {
+ return connection;
+ }
+
+ public Status getStatus() {
+ return status;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public JSONObject extract() {
+ JSONObject object = new JSONObject();
+
+ object.put(STATUS, status.name());
+ object.put(CONNECTOR_PART,
+ extractForms(connection.getConnectorPart().getForms()));
+ object.put(FRAMEWORK_PART,
+ extractForms(connection.getFrameworkPart().getForms()));
+
+ return object;
+ }
+
+ @SuppressWarnings("unchecked")
+ private JSONObject extractForms(List<MForm> forms) {
+ JSONObject ret = new JSONObject();
+
+ for (MForm form : forms) {
+ ret.put(form.getPersistenceId(), extractForm(form));
+ }
+ return ret;
+ }
+
+ @SuppressWarnings("unchecked")
+ private JSONObject extractForm(MForm form) {
+ JSONObject object = new JSONObject();
+
+ for (MInput input : form.getInputs()) {
+ if (input.getValidationSeverity() != MValidatedElement.Severity.OK) {
+ JSONObject validation = new JSONObject();
+ validation.put(SEVERITY, input.getValidationSeverity().name());
+ validation.put(MESSAGE, input.getValidationMessage());
+
+ object.put(input.getPersistenceId(), validation);
+ }
+ }
+
+ return object;
+ }
+
+ @Override
+ public void restore(JSONObject jsonObject) {
+ status = Status.valueOf((String) jsonObject.get(STATUS));
+
+ JSONObject connectorPart = (JSONObject) jsonObject.get(CONNECTOR_PART);
+ JSONObject frameworkPart = (JSONObject) jsonObject.get(FRAMEWORK_PART);
+
+ restoreForms(connectorPart, connection.getConnectorPart().getForms());
+ restoreForms(frameworkPart, connection.getFrameworkPart().getForms());
+ }
+
+ private void restoreForms(JSONObject json, List<MForm> forms) {
+ for (MForm form : forms) {
+ String id = Long.toString(form.getPersistenceId());
+ if (json.containsKey(id)) {
+ restoreForm((JSONObject) json.get(id), form);
+ }
+ }
+ }
+
+ private void restoreForm(JSONObject json, MForm form) {
+ for (MInput input : form.getInputs()) {
+ String id = Long.toString(input.getPersistenceId());
+ if (json.containsKey(id)) {
+ JSONObject validation = (JSONObject) json.get(id);
+
+ MValidatedElement.Severity severity =
+ MValidatedElement.Severity.valueOf((String) validation.get(SEVERITY));
+ String message = (String) validation.get(MESSAGE);
+
+ input.setValidationMessage(severity, message);
+ } else {
+ input.setValidationMessage(MValidatedElement.Severity.OK, null);
+ }
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/47cb311a/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
index ba9cf02..6b7332a 100644
--- a/common/src/main/java/org/apache/sqoop/json/util/FormSerialization.java
+++ b/common/src/main/java/org/apache/sqoop/json/util/FormSerialization.java
@@ -28,7 +28,6 @@ import org.json.simple.JSONObject;
import java.util.ArrayList;
import java.util.List;
-import java.util.Map;
/**
* Convenient static methods for serializing forms.
@@ -48,6 +47,7 @@ public class FormSerialization {
public static final String FORM_INPUT_TYPE = "type";
public static final String FORM_INPUT_MASK = "mask";
public static final String FORM_INPUT_SIZE = "size";
+ public static final String FORM_INPUT_VALUE = "value";
/**
* Transform given list of forms to JSON Array object.
@@ -75,6 +75,7 @@ public class FormSerialization {
@SuppressWarnings("unchecked")
public static JSONObject extractForm(MForm mForm) {
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();
@@ -83,15 +84,22 @@ public class FormSerialization {
for (MInput<?> mInput : mForm.getInputs()) {
JSONObject input = new JSONObject();
mInputs.add(input);
-
+ input.put(ID, mInput.getPersistenceId());
input.put(FORM_INPUT_NAME, mInput.getName());
input.put(FORM_INPUT_TYPE, mInput.getType().toString());
+
+ // String specific serialization
if (mInput.getType() == MInputType.STRING) {
input.put(FORM_INPUT_MASK,
((MStringInput)mInput).isMasked());
input.put(FORM_INPUT_SIZE,
((MStringInput)mInput).getMaxLength());
}
+
+ // Serialize value if is there
+ if(!mInput.isEmpty()) {
+ input.put(FORM_INPUT_VALUE, mInput.getUrlSafeValueString());
+ }
}
return form;
@@ -127,25 +135,36 @@ public class FormSerialization {
JSONObject input = (JSONObject) inputs.get(i);
MInputType type =
MInputType.valueOf((String) input.get(FORM_INPUT_TYPE));
+ MInput mInput = null;
switch (type) {
case STRING: {
String name = (String) input.get(FORM_INPUT_NAME);
boolean mask = (Boolean) input.get(FORM_INPUT_MASK);
long size = (Long) input.get(FORM_INPUT_SIZE);
- MInput<String> mInput = new MStringInput(name, mask, (short) size);
- mInputs.add(mInput);
+ mInput = new MStringInput(name, mask, (short) size);
break;
}
case MAP: {
String name = (String) input.get(FORM_INPUT_NAME);
- MInput<Map<String, String>> mInput = new MMapInput(name);
- mInputs.add(mInput);
+ mInput = new MMapInput(name);
break;
}
}
+
+ // Propagate form ID
+ mInput.setPersistenceId((Long)input.get(ID));
+
+ // Propagate form optional value
+ if(input.containsKey(FORM_INPUT_VALUE)) {
+ mInput.restoreFromUrlSafeValueString(
+ (String) input.get(FORM_INPUT_VALUE));
+ }
+ mInputs.add(mInput);
}
- return new MForm((String) form.get(FORM_NAME), mInputs);
+ MForm mForm = new MForm((String) form.get(FORM_NAME), mInputs);
+ mForm.setPersistenceId((Long) form.get(ID));
+ return mForm;
}
private FormSerialization() {