You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sqoop.apache.org by hs...@apache.org on 2013/08/07 01:22:00 UTC
[2/6] SQOOP-921. Sqoop2: Create standalone shell package
http://git-wip-us.apache.org/repos/asf/sqoop/blob/21c1207b/shell/src/main/java/org/apache/sqoop/shell/StartCommand.java
----------------------------------------------------------------------
diff --git a/shell/src/main/java/org/apache/sqoop/shell/StartCommand.java b/shell/src/main/java/org/apache/sqoop/shell/StartCommand.java
new file mode 100644
index 0000000..f03e08f
--- /dev/null
+++ b/shell/src/main/java/org/apache/sqoop/shell/StartCommand.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.shell;
+
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.apache.sqoop.shell.core.Constants;
+import org.codehaus.groovy.tools.shell.Shell;
+
+import static org.apache.sqoop.shell.ShellEnvironment.printlnResource;
+
+public class StartCommand extends SqoopCommand {
+ public static final Logger LOG = Logger.getLogger(StartCommand.class);
+
+ private StartJobFunction startJobFunction;
+
+ @SuppressWarnings("static-access")
+ protected StartCommand(Shell shell) {
+ super(shell, Constants.CMD_START, Constants.CMD_START_SC,
+ new String[] {Constants.FN_JOB}, Constants.PRE_START, null);
+ }
+
+ @Override
+ public Object executeCommand(List args) {
+ if (args.size() == 0) {
+ printlnResource(Constants.RES_START_USAGE, getUsage());
+ return null;
+ }
+
+ String func = (String) args.get(0);
+ if (func.equals(Constants.FN_JOB)) {
+ if (startJobFunction == null) {
+ startJobFunction = new StartJobFunction();
+ }
+ return startJobFunction.execute(args);
+ } else {
+ printlnResource(Constants.RES_FUNCTION_UNKNOWN, func);
+ }
+
+ return null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/21c1207b/shell/src/main/java/org/apache/sqoop/shell/StartJobFunction.java
----------------------------------------------------------------------
diff --git a/shell/src/main/java/org/apache/sqoop/shell/StartJobFunction.java b/shell/src/main/java/org/apache/sqoop/shell/StartJobFunction.java
new file mode 100644
index 0000000..02148de
--- /dev/null
+++ b/shell/src/main/java/org/apache/sqoop/shell/StartJobFunction.java
@@ -0,0 +1,89 @@
+/**
+ * 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.shell;
+
+import static org.apache.sqoop.shell.ShellEnvironment.client;
+import static org.apache.sqoop.shell.ShellEnvironment.getPollTimeout;
+import static org.apache.sqoop.shell.ShellEnvironment.resourceString;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.OptionBuilder;
+import org.apache.log4j.Logger;
+import org.apache.sqoop.client.SubmissionCallback;
+import org.apache.sqoop.common.SqoopException;
+import org.apache.sqoop.model.MSubmission;
+import org.apache.sqoop.shell.core.ShellError;
+import org.apache.sqoop.shell.core.Constants;
+import org.apache.sqoop.shell.utils.SubmissionDisplayer;
+
+public class StartJobFunction extends SqoopFunction {
+ public static final Logger LOG = Logger.getLogger(StartJobFunction.class);
+
+ @SuppressWarnings("static-access")
+ public StartJobFunction() {
+ this.addOption(OptionBuilder.hasArg().withArgName(Constants.OPT_JID)
+ .withDescription(resourceString(Constants.RES_PROMPT_JOB_ID))
+ .withLongOpt(Constants.OPT_JID)
+ .create(Constants.OPT_JID_CHAR));
+ this.addOption(OptionBuilder
+ .withDescription(resourceString(Constants.RES_PROMPT_SYNCHRONOUS))
+ .withLongOpt(Constants.OPT_SYNCHRONOUS)
+ .create(Constants.OPT_SYNCHRONOUS_CHAR));
+ }
+
+ @Override
+ public Object executeFunction(CommandLine line) {
+ // Poll until finished
+ if (line.hasOption(Constants.OPT_SYNCHRONOUS) && line.hasOption(Constants.OPT_JID)) {
+ long pollTimeout = getPollTimeout();
+ SubmissionCallback callback = new SubmissionCallback() {
+ @Override
+ public void submitted(MSubmission submission) {
+ SubmissionDisplayer.displayHeader(submission);
+ SubmissionDisplayer.displayProgress(submission);
+ }
+
+ @Override
+ public void updated(MSubmission submission) {
+ SubmissionDisplayer.displayProgress(submission);
+ }
+
+ @Override
+ public void finished(MSubmission submission) {
+ SubmissionDisplayer.displayFooter(submission);
+ }
+ };
+
+ try {
+ client.startSubmission(getLong(line, Constants.OPT_JID), callback, pollTimeout);
+ } catch (InterruptedException e) {
+ throw new SqoopException(ShellError.SHELL_0008, e);
+ }
+ } else if (line.hasOption(Constants.OPT_JID)) {
+ MSubmission submission = client.startSubmission(getLong(line, Constants.OPT_JID));
+ if(submission.getStatus().isFailure()) {
+ SubmissionDisplayer.displayFooter(submission);
+ } else {
+ SubmissionDisplayer.displayHeader(submission);
+ SubmissionDisplayer.displayProgress(submission);
+ }
+ }
+
+ return null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/21c1207b/shell/src/main/java/org/apache/sqoop/shell/StatusCommand.java
----------------------------------------------------------------------
diff --git a/shell/src/main/java/org/apache/sqoop/shell/StatusCommand.java b/shell/src/main/java/org/apache/sqoop/shell/StatusCommand.java
new file mode 100644
index 0000000..184892a
--- /dev/null
+++ b/shell/src/main/java/org/apache/sqoop/shell/StatusCommand.java
@@ -0,0 +1,56 @@
+/**
+ * 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.shell;
+
+import java.util.List;
+
+import org.apache.sqoop.shell.core.Constants;
+import org.codehaus.groovy.tools.shell.Shell;
+
+import static org.apache.sqoop.shell.ShellEnvironment.printlnResource;
+
+public class StatusCommand extends SqoopCommand {
+
+ private StatusJobFunction statusJobFunction;
+
+ @SuppressWarnings("static-access")
+ protected StatusCommand(Shell shell) {
+ super(shell, Constants.CMD_STATUS, Constants.CMD_STATUS_SC,
+ new String[] { Constants.FN_JOB }, Constants.PRE_STATUS, null);
+ }
+
+ @Override
+ public Object executeCommand(List args) {
+ if (args.size() == 0) {
+ printlnResource(Constants.RES_STATUS_USAGE, getUsage());
+ return null;
+ }
+
+ String func = (String) args.get(0);
+ if (func.equals(Constants.FN_JOB)) {
+ if (statusJobFunction == null) {
+ statusJobFunction = new StatusJobFunction();
+ }
+ return statusJobFunction.execute(args);
+ } else {
+ printlnResource(Constants.RES_FUNCTION_UNKNOWN, func);
+ }
+
+ return null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/21c1207b/shell/src/main/java/org/apache/sqoop/shell/StatusJobFunction.java
----------------------------------------------------------------------
diff --git a/shell/src/main/java/org/apache/sqoop/shell/StatusJobFunction.java b/shell/src/main/java/org/apache/sqoop/shell/StatusJobFunction.java
new file mode 100644
index 0000000..be0de8c
--- /dev/null
+++ b/shell/src/main/java/org/apache/sqoop/shell/StatusJobFunction.java
@@ -0,0 +1,55 @@
+/**
+ * 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.shell;
+
+import static org.apache.sqoop.shell.ShellEnvironment.client;
+import static org.apache.sqoop.shell.ShellEnvironment.resourceString;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.OptionBuilder;
+import org.apache.sqoop.model.MSubmission;
+import org.apache.sqoop.shell.core.Constants;
+import org.apache.sqoop.shell.utils.SubmissionDisplayer;
+import org.apache.sqoop.submission.SubmissionStatus;
+
+public class StatusJobFunction extends SqoopFunction{
+
+ @SuppressWarnings("static-access")
+ public StatusJobFunction() {
+ this.addOption(OptionBuilder.hasArg().withArgName(Constants.OPT_JID)
+ .withDescription(resourceString(Constants.RES_PROMPT_JOB_ID))
+ .withLongOpt(Constants.OPT_JID)
+ .create(Constants.OPT_JID_CHAR));
+ }
+
+ @Override
+ public Object executeFunction(CommandLine line) {
+ if (line.hasOption(Constants.OPT_JID)) {
+ MSubmission submission = client.getSubmissionStatus(getLong(line, Constants.OPT_JID));
+ if(submission.getStatus().isFailure() || submission.getStatus().equals(SubmissionStatus.SUCCEEDED)) {
+ SubmissionDisplayer.displayHeader(submission);
+ SubmissionDisplayer.displayFooter(submission);
+ } else {
+ SubmissionDisplayer.displayHeader(submission);
+ SubmissionDisplayer.displayProgress(submission);
+ }
+ }
+
+ return null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/21c1207b/shell/src/main/java/org/apache/sqoop/shell/StopCommand.java
----------------------------------------------------------------------
diff --git a/shell/src/main/java/org/apache/sqoop/shell/StopCommand.java b/shell/src/main/java/org/apache/sqoop/shell/StopCommand.java
new file mode 100644
index 0000000..698bca7
--- /dev/null
+++ b/shell/src/main/java/org/apache/sqoop/shell/StopCommand.java
@@ -0,0 +1,54 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sqoop.shell;
+
+import java.util.List;
+
+import org.apache.sqoop.shell.core.Constants;
+import org.codehaus.groovy.tools.shell.Shell;
+
+import static org.apache.sqoop.shell.ShellEnvironment.printlnResource;
+
+public class StopCommand extends SqoopCommand {
+
+ private StopJobFunction stopJobFunction;
+
+ @SuppressWarnings("static-access")
+ protected StopCommand(Shell shell) {
+ super(shell, Constants.CMD_STOP, Constants.CMD_STOP_SC,
+ new String[] { Constants.FN_JOB }, Constants.PRE_STOP, null);
+ }
+ @Override
+ public Object executeCommand(List args) {
+ if (args.size() == 0) {
+ printlnResource(Constants.RES_STOP_USAGE, getUsage());
+ return null;
+ }
+
+ String func = (String) args.get(0);
+ if (func.equals(Constants.FN_JOB)) {
+ if (stopJobFunction == null) {
+ stopJobFunction = new StopJobFunction();
+ }
+ return stopJobFunction.execute(args);
+ } else {
+ printlnResource(Constants.RES_FUNCTION_UNKNOWN, func);
+ }
+ return null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/21c1207b/shell/src/main/java/org/apache/sqoop/shell/StopJobFunction.java
----------------------------------------------------------------------
diff --git a/shell/src/main/java/org/apache/sqoop/shell/StopJobFunction.java b/shell/src/main/java/org/apache/sqoop/shell/StopJobFunction.java
new file mode 100644
index 0000000..6c0e3c2
--- /dev/null
+++ b/shell/src/main/java/org/apache/sqoop/shell/StopJobFunction.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.shell;
+
+import static org.apache.sqoop.shell.ShellEnvironment.client;
+import static org.apache.sqoop.shell.ShellEnvironment.resourceString;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.OptionBuilder;
+import org.apache.sqoop.model.MSubmission;
+import org.apache.sqoop.shell.core.Constants;
+import org.apache.sqoop.shell.utils.SubmissionDisplayer;
+
+public class StopJobFunction extends SqoopFunction {
+
+ @SuppressWarnings("static-access")
+ public StopJobFunction() {
+ this.addOption(OptionBuilder.hasArg().withArgName(Constants.OPT_JID)
+ .withDescription(resourceString(Constants.RES_PROMPT_JOB_ID))
+ .withLongOpt(Constants.OPT_JID)
+ .create(Constants.OPT_JID_CHAR));
+ }
+
+ @Override
+ public Object executeFunction(CommandLine line) {
+ if (line.hasOption(Constants.OPT_JID)) {
+ MSubmission submission = client.stopSubmission(getLong(line, Constants.OPT_JID));
+ if(submission.getStatus().isFailure()) {
+ SubmissionDisplayer.displayFooter(submission);
+ } else {
+ SubmissionDisplayer.displayHeader(submission);
+ SubmissionDisplayer.displayProgress(submission);
+ }
+ }
+
+ return null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/21c1207b/shell/src/main/java/org/apache/sqoop/shell/UpdateCommand.java
----------------------------------------------------------------------
diff --git a/shell/src/main/java/org/apache/sqoop/shell/UpdateCommand.java b/shell/src/main/java/org/apache/sqoop/shell/UpdateCommand.java
new file mode 100644
index 0000000..9262ccd
--- /dev/null
+++ b/shell/src/main/java/org/apache/sqoop/shell/UpdateCommand.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.shell;
+
+import org.apache.sqoop.common.SqoopException;
+import org.apache.sqoop.shell.core.ShellError;
+import org.apache.sqoop.shell.core.Constants;
+import org.codehaus.groovy.tools.shell.Shell;
+
+import java.util.List;
+
+import static org.apache.sqoop.shell.ShellEnvironment.*;
+
+/**
+ *
+ */
+public class UpdateCommand extends SqoopCommand {
+
+ private UpdateConnectionFunction connectionFunction;
+ private UpdateJobFunction jobFunction;
+
+ public UpdateCommand(Shell shell) {
+ super(shell, Constants.CMD_UPDATE, Constants.CMD_UPDATE_SC,
+ new String[] {Constants.FN_CONNECTION, Constants.FN_JOB},
+ Constants.PRE_UPDATE, Constants.SUF_INFO);
+ }
+
+ public Object executeCommand(List args) {
+ if(!isInteractive()) {
+ throw new SqoopException(ShellError.SHELL_0007, "update");
+ }
+
+ if (args.size() == 0) {
+ printlnResource(Constants.RES_UPDATE_USAGE, getUsage());
+ return null;
+ }
+
+ String func = (String)args.get(0);
+ if (func.equals(Constants.FN_CONNECTION)) {
+ if (connectionFunction == null) {
+ connectionFunction = new UpdateConnectionFunction();
+ }
+ return connectionFunction.execute(args);
+ } else if (func.equals(Constants.FN_JOB)) {
+ if (jobFunction == null) {
+ jobFunction = new UpdateJobFunction();
+ }
+ return jobFunction.execute(args);
+ } else {
+ printlnResource(Constants.RES_FUNCTION_UNKNOWN, func);
+ return null;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/21c1207b/shell/src/main/java/org/apache/sqoop/shell/UpdateConnectionFunction.java
----------------------------------------------------------------------
diff --git a/shell/src/main/java/org/apache/sqoop/shell/UpdateConnectionFunction.java b/shell/src/main/java/org/apache/sqoop/shell/UpdateConnectionFunction.java
new file mode 100644
index 0000000..c062fe6
--- /dev/null
+++ b/shell/src/main/java/org/apache/sqoop/shell/UpdateConnectionFunction.java
@@ -0,0 +1,97 @@
+/**
+ * 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.shell;
+
+import jline.ConsoleReader;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.OptionBuilder;
+import org.apache.sqoop.common.SqoopException;
+import org.apache.sqoop.model.MConnection;
+import org.apache.sqoop.shell.core.ShellError;
+import org.apache.sqoop.shell.core.Constants;
+import org.apache.sqoop.shell.utils.FormDisplayer;
+import org.apache.sqoop.validation.Status;
+
+import java.io.IOException;
+import java.util.ResourceBundle;
+
+import static org.apache.sqoop.shell.ShellEnvironment.*;
+import static org.apache.sqoop.shell.utils.FormFiller.*;
+
+/**
+ *
+ */
+public class UpdateConnectionFunction extends SqoopFunction {
+ @SuppressWarnings("static-access")
+ public UpdateConnectionFunction() {
+ this.addOption(OptionBuilder
+ .withDescription(resourceString(Constants.RES_PROMPT_CONN_ID))
+ .withLongOpt(Constants.OPT_XID)
+ .hasArg()
+ .create(Constants.OPT_XID_CHAR));
+ }
+
+ public Object executeFunction(CommandLine line) {
+ if (!line.hasOption(Constants.OPT_XID)) {
+ printlnResource(Constants.RES_ARGS_XID_MISSING);
+ return null;
+ }
+
+ try {
+ updateConnection(getLong(line, Constants.OPT_XID));
+ } catch (IOException ex) {
+ throw new SqoopException(ShellError.SHELL_0005, ex);
+ }
+
+ return null;
+ }
+
+ private void updateConnection(Long connectionId) throws IOException {
+ printlnResource(Constants.RES_UPDATE_UPDATING_CONN, connectionId);
+
+ ConsoleReader reader = new ConsoleReader();
+
+ MConnection connection = client.getConnection(connectionId);
+
+ ResourceBundle connectorBundle = client.getResourceBundle(connection.getConnectorId());
+ ResourceBundle frameworkBundle = client.getFrameworkResourceBundle();
+
+ Status status = Status.FINE;
+
+ printlnResource(Constants.RES_PROMPT_UPDATE_CONN_METADATA);
+
+ do {
+ // Print error introduction if needed
+ if( !status.canProceed() ) {
+ errorIntroduction();
+ }
+
+ // Fill in data from user
+ if(!fillConnection(reader, connection, connectorBundle, frameworkBundle)) {
+ return;
+ }
+
+ // Try to create
+ status = client.updateConnection(connection);
+ } while(!status.canProceed());
+ FormDisplayer.displayFormWarning(connection);
+ printlnResource(Constants.RES_UPDATE_CONN_SUCCESSFUL, status.name());
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/21c1207b/shell/src/main/java/org/apache/sqoop/shell/UpdateJobFunction.java
----------------------------------------------------------------------
diff --git a/shell/src/main/java/org/apache/sqoop/shell/UpdateJobFunction.java b/shell/src/main/java/org/apache/sqoop/shell/UpdateJobFunction.java
new file mode 100644
index 0000000..da1e0c5
--- /dev/null
+++ b/shell/src/main/java/org/apache/sqoop/shell/UpdateJobFunction.java
@@ -0,0 +1,95 @@
+/**
+ * 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.shell;
+
+import jline.ConsoleReader;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.OptionBuilder;
+import org.apache.sqoop.common.SqoopException;
+import org.apache.sqoop.model.MJob;
+import org.apache.sqoop.shell.core.ShellError;
+import org.apache.sqoop.shell.core.Constants;
+import org.apache.sqoop.shell.utils.FormDisplayer;
+import org.apache.sqoop.validation.Status;
+
+import java.io.IOException;
+import java.util.ResourceBundle;
+
+import static org.apache.sqoop.shell.ShellEnvironment.*;
+import static org.apache.sqoop.shell.utils.FormFiller.*;
+
+/**
+ *
+ */
+public class UpdateJobFunction extends SqoopFunction {
+ @SuppressWarnings("static-access")
+ public UpdateJobFunction() {
+ this.addOption(OptionBuilder
+ .withDescription(resourceString(Constants.RES_PROMPT_JOB_ID))
+ .withLongOpt(Constants.OPT_JID)
+ .hasArg()
+ .create(Constants.OPT_JID_CHAR));
+ }
+
+ public Object executeFunction(CommandLine line) {
+ if (!line.hasOption(Constants.OPT_JID)) {
+ printlnResource(Constants.RES_ARGS_JID_MISSING);
+ return null;
+ }
+
+ try {
+ updateJob(getLong(line, Constants.OPT_JID));
+ } catch (IOException ex) {
+ throw new SqoopException(ShellError.SHELL_0005, ex);
+ }
+
+ return null;
+ }
+
+ private void updateJob(Long jobId) throws IOException {
+ printlnResource(Constants.RES_UPDATE_UPDATING_JOB, jobId);
+
+ ConsoleReader reader = new ConsoleReader();
+
+ MJob job = client.getJob(jobId);
+
+ ResourceBundle connectorBundle = client.getResourceBundle(job.getConnectorId());
+ ResourceBundle frameworkBundle = client.getFrameworkResourceBundle();
+
+ Status status = Status.FINE;
+
+ printlnResource(Constants.RES_PROMPT_UPDATE_JOB_METADATA);
+
+ do {
+ // Print error introduction if needed
+ if( !status.canProceed() ) {
+ errorIntroduction();
+ }
+
+ // Fill in data from user
+ if(!fillJob(reader, job, connectorBundle, frameworkBundle)) {
+ return;
+ }
+
+ // Try to create
+ status = client.updateJob(job);
+ } while(!status.canProceed());
+ FormDisplayer.displayFormWarning(job);
+ printlnResource(Constants.RES_UPDATE_JOB_SUCCESSFUL, status.name());
+ }
+}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/21c1207b/shell/src/main/java/org/apache/sqoop/shell/core/Constants.java
----------------------------------------------------------------------
diff --git a/shell/src/main/java/org/apache/sqoop/shell/core/Constants.java b/shell/src/main/java/org/apache/sqoop/shell/core/Constants.java
new file mode 100644
index 0000000..0e33d42
--- /dev/null
+++ b/shell/src/main/java/org/apache/sqoop/shell/core/Constants.java
@@ -0,0 +1,451 @@
+/**
+ * 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.shell.core;
+
+/**
+ *
+ */
+public class Constants {
+
+ // General string constants
+ public static final String RESOURCE_NAME = "shell-resource";
+ public static final String BOLD_STR_SEQUENCE = "@|bold";
+ public static final String END_STR_SEQUENCE = "|@";
+
+ // Environmental variables
+ public static final String ENV_HOST = "SQOOP2_HOST";
+ public static final String ENV_PORT = "SQOOP2_PORT";
+ public static final String ENV_WEBAPP = "SQOOP2_WEBAPP";
+
+ // Options
+
+ public static final String OPT_XID = "xid";
+ public static final String OPT_ALL = "all";
+ public static final String OPT_JID = "jid";
+ public static final String OPT_CID = "cid";
+ public static final String OPT_TYPE = "type";
+ public static final String OPT_NAME = "name";
+ public static final String OPT_VALUE = "value";
+ public static final String OPT_VERBOSE = "verbose";
+ public static final String OPT_HOST = "host";
+ public static final String OPT_PORT = "port";
+ public static final String OPT_WEBAPP = "webapp";
+ public static final String OPT_URL = "url";
+ public static final String OPT_SERVER = "server";
+ public static final String OPT_CLIENT = "client";
+ public static final String OPT_PROTOCOL = "protocol";
+ public static final String OPT_SYNCHRONOUS = "synchronous";
+ public static final String OPT_POLL_TIMEOUT = "poll-timeout";
+ public static final String OPT_DETAIL = "detail";
+
+ public static final char OPT_XID_CHAR = 'x';
+ public static final char OPT_ALL_CHAR = 'a';
+ public static final char OPT_JID_CHAR = 'j';
+ public static final char OPT_CID_CHAR = 'c';
+ public static final char OPT_TYPE_CHAR = 't';
+ public static final char OPT_NAME_CHAR = 'n';
+ public static final char OPT_VALUE_CHAR = 'v';
+ public static final char OPT_HOST_CHAR = 'h';
+ public static final char OPT_PORT_CHAR = 'p';
+ public static final char OPT_WEBAPP_CHAR = 'w';
+ public static final char OPT_URL_CHAR = 'u';
+ public static final char OPT_SERVER_CHAR = 's';
+ public static final char OPT_CLIENT_CHAR = 'c';
+ public static final char OPT_PROTOCOL_CHAR = 'p';
+ public static final char OPT_SYNCHRONOUS_CHAR = 's';
+ public static final char OPT_POLL_TIMEOUT_CHAR = 'p';
+ public static final char OPT_DETAIL_CHAR = 'd';
+
+ // Resource keys for various commands, command options,
+ // functions and descriptions
+ public static final String CMD_CLONE = "clone";
+ public static final String CMD_CLONE_SC = "\\cl";
+
+ public static final String CMD_CREATE = "create";
+ public static final String CMD_CREATE_SC = "\\cr";
+
+ public static final String CMD_DELETE = "delete";
+ public static final String CMD_DELETE_SC = "\\d";
+
+ public static final String CMD_HELP = "help";
+ public static final String CMD_HELP_SC = "\\h";
+
+ public static final String CMD_SET = "set";
+ public static final String CMD_SET_SC = "\\st";
+
+ public static final String CMD_SHOW = "show";
+ public static final String CMD_SHOW_SC = "\\sh";
+
+ public static final String CMD_UPDATE = "update";
+ public static final String CMD_UPDATE_SC = "\\up";
+
+ public static final String CMD_START = "start";
+ public static final String CMD_START_SC = "\\sta";
+
+ public static final String CMD_STOP = "stop";
+ public static final String CMD_STOP_SC = "\\stp";
+
+ public static final String CMD_STATUS = "status";
+ public static final String CMD_STATUS_SC = "\\stu";
+
+ public static final String CMD_ENABLE = "enable";
+ public static final String CMD_ENABLE_SC = "\\en";
+
+ public static final String CMD_DISABLE = "disable";
+ public static final String CMD_DISABLE_SC = "\\di";
+
+ public static final String FN_CONNECTION = "connection";
+ public static final String FN_JOB = "job";
+ public static final String FN_SUBMISSION = "submission";
+ public static final String FN_SERVER = "server";
+ public static final String FN_OPTION = "option";
+ public static final String FN_CONNECTOR = "connector";
+ public static final String FN_VERSION = "version";
+ public static final String FN_FRAMEWORK = "framework";
+
+ public static final String PRE_CLONE = "Clone";
+ public static final String PRE_CREATE = "Create";
+ public static final String PRE_DELETE = "Delete";
+ public static final String PRE_SET = "Set";
+ public static final String PRE_SHOW = "Show";
+ public static final String PRE_UPDATE = "Update";
+ public static final String PRE_START = "Start";
+ public static final String PRE_STATUS = "Status";
+ public static final String PRE_STOP = "Stop";
+ public static final String PRE_ENABLE = "Enable";
+ public static final String PRE_DISABLE = "Disable";
+ public static final String SUF_INFO = "Info";
+
+
+ public static final String PROP_HOMEDIR = "user.home";
+ public static final String PROP_CURDIR = "user.dir";
+ public static final String SQOOP_PROMPT = "sqoop";
+
+
+ // Resource Keys for various messages
+
+ public static final String RES_FUNCTION_UNKNOWN =
+ "args.function.unknown";
+ public static final String RES_ARGS_XID_MISSING =
+ "args.xid_missing";
+ public static final String RES_ARGS_JID_MISSING =
+ "args.jid_missing";
+ public static final String RES_ARGS_CID_MISSING =
+ "args.cid_missing";
+ public static final String RES_ARGS_TYPE_MISSING =
+ "args.type_missing";
+ public static final String RES_ARGS_NAME_MISSING =
+ "args.name_missing";
+ public static final String RES_ARGS_VALUE_MISSING =
+ "args.value_missing";
+
+ public static final String RES_PROMPT_CONN_ID =
+ "prompt.conn_id";
+ public static final String RES_PROMPT_JOB_ID =
+ "prompt.job_id";
+ public static final String RES_CONNECTOR_ID =
+ "prompt.connector_id";
+ public static final String RES_PROMPT_JOB_TYPE =
+ "prompt.job_type";
+ public static final String RES_PROMPT_UPDATE_CONN_METADATA =
+ "prompt.update_conn_metadata";
+ public static final String RES_PROMPT_UPDATE_JOB_METADATA =
+ "prompt.update_job_metadata";
+ public static final String RES_PROMPT_FILL_CONN_METADATA =
+ "prompt.fill_conn_metadata";
+ public static final String RES_PROMPT_FILL_JOB_METADATA =
+ "prompt.fill_job_metadata";
+
+ public static final String RES_CLONE_USAGE =
+ "clone.usage";
+ public static final String RES_CLONE_CONN_SUCCESSFUL =
+ "clone.conn.successful";
+ public static final String RES_CLONE_JOB_SUCCESSFUL =
+ "clone.job.successful";
+ public static final String RES_CLONE_CLONING_CONN =
+ "clone.cloning_conn";
+ public static final String RES_CLONE_CLONING_JOB =
+ "clone.cloning_job";
+
+ public static final String RES_CREATE_USAGE =
+ "create.usage";
+ public static final String RES_CREATE_CONN_SUCCESSFUL =
+ "create.conn_successful";
+ public static final String RES_CREATE_JOB_SUCCESSFUL =
+ "create.job_successful";
+ public static final String RES_CREATE_CREATING_CONN =
+ "create.creating_conn";
+ public static final String RES_CREATE_CREATING_JOB =
+ "create.creating_job";
+
+ public static final String RES_DELETE_USAGE =
+ "delete.usage";
+
+ public static final String RES_DISABLE_USAGE =
+ "disable.usage";
+ public static final String RES_DISABLE_CONNECTION_SUCCESSFUL =
+ "disable.conn_successful";
+ public static final String RES_DISABLE_JOB_SUCCESSFUL =
+ "disable.job_successful";
+
+ public static final String RES_ENABLE_USAGE =
+ "enable.usage";
+ public static final String RES_ENABLE_CONNECTION_SUCCESSFUL =
+ "enable.conn_successful";
+ public static final String RES_ENABLE_JOB_SUCCESSFUL =
+ "enable.job_successful";
+
+ public static final String RES_HELP_USAGE =
+ "help.usage";
+ public static final String RES_HELP_DESCRIPTION =
+ "help.description";
+ public static final String RES_HELP_CMD_USAGE =
+ "help.cmd_usage";
+ public static final String RES_HELP_MESSAGE =
+ "help.message";
+ public static final String RES_HELP_INFO =
+ "help.info";
+ public static final String RES_HELP_AVAIL_COMMANDS =
+ "help.avail_commands";
+ public static final String RES_HELP_CMD_DESCRIPTION =
+ "help.cmd_description";
+ public static final String RES_HELP_SPECIFIC_CMD_INFO =
+ "help.specific_cmd_info";
+
+ public static final String RES_UNRECOGNIZED_CMD =
+ "unrecognized.cmd";
+
+ public static final String RES_SET_USAGE =
+ "set.usage";
+ public static final String RES_SET_PROMPT_OPT_NAME =
+ "set.prompt_opt_name";
+ public static final String RES_SET_PROMPT_OPT_VALUE =
+ "set.prompt_opt_value";
+ public static final String RES_SET_VERBOSE_CHANGED =
+ "set.verbose_changed";
+ public static final String RES_SET_POLL_TIMEOUT_CHANGED =
+ "set.poll_timeout_changed";
+ public static final String RES_SET_UNKNOWN_OPT_IGNORED =
+ "set.unknown_opt_ignored";
+ public static final String RES_SET_HOST_DESCRIPTION =
+ "set.host_description";
+ public static final String RES_SET_PORT_DESCRIPTION =
+ "set.port_description";
+ public static final String RES_WEBAPP_DESCRIPTION =
+ "set.webapp_description";
+ public static final String RES_URL_DESCRIPTION =
+ "set.url_description";
+ public static final String RES_SET_SERVER_USAGE =
+ "set.server_usage";
+ public static final String RES_SET_SERVER_SUCCESSFUL =
+ "set.server_successful";
+ public static final String RES_SET_SERVER_IGNORED =
+ "set.server_ignored";
+
+ public static final String RES_SHOW_USAGE =
+ "show.usage";
+ public static final String RES_SHOW_PROMPT_DISPLAY_ALL_CONNS =
+ "show.prompt_display_all_conns";
+ public static final String RES_SHOW_PROMPT_DISPLAY_CONN_XID =
+ "show.prompt_display_conn_xid";
+ public static final String RES_SHOW_CONN_USAGE =
+ "show.conn_usage";
+ public static final String RES_SHOW_PROMPT_CONNS_TO_SHOW =
+ "show.prompt_conns_to_show";
+ public static final String RES_SHOW_PROMPT_CONN_INFO =
+ "show.prompt_conn_info";
+ public static final String RES_SHOW_PROMPT_CONN_CID_INFO =
+ "show.prompt_conn_cid_info";
+
+ public static final String RES_SHOW_PROMPT_DISPLAY_ALL_CONNECTORS =
+ "show.prompt_display_all_connectors";
+ public static final String RES_SHOW_PROMPT_DISPLAY_CONNECTOR_CID =
+ "show.prompt_display_connector_cid";
+ public static final String RES_SHOW_CONNECTOR_USAGE =
+ "show.connector_usage";
+ public static final String RES_SHOW_PROMPT_CONNECTORS_TO_SHOW =
+ "show.prompt_connectors_to_show";
+ public static final String RES_SHOW_PROMPT_CONNECTOR_INFO =
+ "show.prompt_connector_info";
+
+ public static final String RES_SHOW_FRAMEWORK_USAGE =
+ "show.framework_usage";
+ public static final String RES_SHOW_PROMPT_FRAMEWORK_OPTS =
+ "show.prompt_framework_opts";
+
+ public static final String RES_SHOW_PROMPT_DISPLAY_ALL_JOBS =
+ "show.prompt_display_all_jobs";
+ public static final String RES_SHOW_PROMPT_DISPLAY_JOB_JID =
+ "show.prompt_display_job_jid";
+ public static final String RES_SHOW_JOB_USAGE =
+ "show.job_usage";
+ public static final String RES_SHOW_PROMPT_JOBS_TO_SHOW =
+ "show.prompt_jobs_to_show";
+ public static final String RES_SHOW_PROMPT_JOB_INFO =
+ "show.prompt_job_info";
+ public static final String RES_SHOW_PROMPT_JOB_XID_CID_INFO =
+ "show.prompt_job_xid_cid_info";
+
+ public static final String RES_SHOW_PROMPT_DISPLAY_ALL_SUBMISSIONS =
+ "show.prompt_display_all_submissions";
+ public static final String RES_SHOW_PROMPT_DISPLAY_ALL_SUBMISSIONS_JOB_ID =
+ "show.prompt_display_all_submissions_jid";
+
+ public static final String RES_SHOW_PROMPT_DISPLAY_ALL_SERVERS =
+ "show.prompt_display_all_servers";
+ public static final String RES_SHOW_PROMPT_DISPLAY_SERVER_HOST =
+ "show.prompt_display_server_host";
+ public static final String RES_SHOW_PROMPT_DISPLAY_SERVER_PORT =
+ "show.prompt_display_server_port";
+ public static final String RES_SHOW_PROMPT_DISPLAY_SERVER_WEBAPP =
+ "show.prompt_display_server_webapp";
+ public static final String RES_SHOW_SERVER_USAGE =
+ "show.server_usage";
+ public static final String RES_SHOW_PROMPT_SERVER_HOST =
+ "show.prompt_server_host";
+ public static final String RES_SHOW_PROMPT_SERVER_PORT =
+ "show.prompt_server_port";
+ public static final String RES_SHOW_PROMPT_SERVER_WEBAPP =
+ "show.prompt_server_webapp";
+
+ public static final String RES_SHOW_PROMPT_DISPLAY_ALL_VERSIONS =
+ "show.prompt_display_all_versions";
+ public static final String RES_SHOW_PROMPT_DISPLAY_VERSION_SERVER =
+ "show.prompt_display_version_server";
+ public static final String RES_SHOW_PROMPT_DISPLAY_VERSION_CLIENT =
+ "show.prompt_display_version_client";
+ public static final String RES_SHOW_PROMPT_DISPLAY_VERSION_PROTOCOL =
+ "show.prompt_display_version_protocol";
+ public static final String RES_SHOW_VERSION_USAGE =
+ "show.version_usage";
+ public static final String RES_SHOW_PROMPT_VERSION_CLIENT_SERVER =
+ "show.prompt_version_client_server";
+ public static final String RES_SHOW_PROMPT_VERSION_PROTOCOL =
+ "show.prompt_version_protocol";
+
+ public static final String RES_START_USAGE =
+ "start.usage";
+
+ public static final String RES_STATUS_USAGE =
+ "status.usage";
+ public static final String RES_PROMPT_SYNCHRONOUS =
+ "start.prompt_synchronous";
+
+ public static final String RES_STOP_USAGE =
+ "stop.usage";
+
+ public static final String RES_SQOOP_SHELL_BANNER =
+ "sqoop.shell_banner";
+ public static final String RES_SQOOP_PROMPT_SHELL_LOADRC =
+ "sqoop.prompt_shell_loadrc";
+ public static final String RES_SQOOP_PROMPT_SHELL_LOADEDRC =
+ "sqoop.prompt_shell_loadedrc";
+
+ public static final String RES_UPDATE_USAGE =
+ "update.usage";
+ public static final String RES_UPDATE_UPDATING_CONN =
+ "update.conn";
+ public static final String RES_UPDATE_CONN_SUCCESSFUL =
+ "update.conn_successful";
+ public static final String RES_UPDATE_UPDATING_JOB =
+ "update.job";
+ public static final String RES_UPDATE_JOB_SUCCESSFUL =
+ "update.job_successful";
+
+ public static final String RES_TABLE_HEADER_ID =
+ "table.header.id";
+ public static final String RES_TABLE_HEADER_NAME =
+ "table.header.name";
+ public static final String RES_TABLE_HEADER_VERSION =
+ "table.header.version";
+ public static final String RES_TABLE_HEADER_CLASS =
+ "table.header.class";
+ public static final String RES_TABLE_HEADER_TYPE =
+ "table.header.type";
+ public static final String RES_TABLE_HEADER_CONNECTOR =
+ "table.header.connector";
+ public static final String RES_TABLE_HEADER_JOB_ID =
+ "table.header.jid";
+ public static final String RES_TABLE_HEADER_EXTERNAL_ID =
+ "table.header.eid";
+ public static final String RES_TABLE_HEADER_STATUS =
+ "table.header.status";
+ public static final String RES_TABLE_HEADER_DATE =
+ "table.header.date";
+ public static final String RES_TABLE_HEADER_ENABLED =
+ "table.header.enabled";
+
+ public static final String RES_FORMDISPLAYER_SUPPORTED_JOBTYPE =
+ "formdisplayer.supported_job_types";
+ public static final String RES_FORMDISPLAYER_CONNECTION =
+ "formdisplayer.connection";
+ public static final String RES_FORMDISPLAYER_JOB =
+ "formdisplayer.job";
+ public static final String RES_FORMDISPLAYER_FORM_JOBTYPE =
+ "formdisplayer.forms_jobtype";
+ public static final String RES_FORMDISPLAYER_FORM =
+ "formdisplayer.form";
+ public static final String RES_FORMDISPLAYER_NAME =
+ "formdisplayer.name";
+ public static final String RES_FORMDISPLAYER_LABEL =
+ "formdisplayer.label";
+ public static final String RES_FORMDISPLAYER_HELP =
+ "formdisplayer.help";
+ public static final String RES_FORMDISPLAYER_INPUT =
+ "formdisplayer.input";
+ public static final String RES_FORMDISPLAYER_TYPE =
+ "formdisplayer.type";
+ public static final String RES_FORMDISPLAYER_SENSITIVE =
+ "formdisplayer.sensitive";
+ public static final String RES_FORMDISPLAYER_SIZE =
+ "formdisplayer.size";
+ public static final String RES_FORMDISPLAYER_POSSIBLE_VALUES =
+ "formdisplayer.possible_values";
+ public static final String RES_FORMDISPLAYER_UNSUPPORTED_DATATYPE =
+ "formdisplayer.unsupported_datatype";
+ public static final String RES_FORMDISPLAYER_INPUT_SENSITIVE =
+ "formdisplayer.input_sensitive";
+
+ public static final String RES_FORMDISPLAYER_FORM_WARNING =
+ "formdisplayer.warning_message";
+
+ public static final String RES_SUBMISSION_SUBMISSION_DETAIL =
+ "submission.submission_detail";
+ public static final String RES_SUBMISSION_JOB_ID =
+ "submission.job_id";
+ public static final String RES_SUBMISSION_CREATION_DATE =
+ "submission.creation_date";
+ public static final String RES_SUBMISSION_EXTERNAL_ID =
+ "submission.external_id";
+ public static final String RES_SUBMISSION_PROGRESS_NOT_AVAIL =
+ "submission.progress_not_available";
+ public static final String RES_SUBMISSION_COUNTERS =
+ "submission.counters";
+ public static final String RES_SUBMISSION_EXECUTED_SUCCESS =
+ "submission.executed_success";
+ public static final String RES_SUBMISSION_SERVER_URL =
+ "submission.server_url";
+ public static final String RES_CONNECTOR_SCHEMA =
+ "submission.connector_schema";
+ public static final String RES_HIO_SCHEMA =
+ "submission.hio_schema";
+
+ private Constants() {
+ // Instantiation is prohibited
+ }
+}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/21c1207b/shell/src/main/java/org/apache/sqoop/shell/core/ShellError.java
----------------------------------------------------------------------
diff --git a/shell/src/main/java/org/apache/sqoop/shell/core/ShellError.java b/shell/src/main/java/org/apache/sqoop/shell/core/ShellError.java
new file mode 100644
index 0000000..e5a99f1
--- /dev/null
+++ b/shell/src/main/java/org/apache/sqoop/shell/core/ShellError.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.shell.core;
+
+import org.apache.sqoop.common.ErrorCode;
+
+public enum ShellError implements ErrorCode {
+
+ /** An unknown error has occurred. */
+ SHELL_0000("An unknown error has occurred"),
+
+ /** The specified command is not recognized. */
+ SHELL_0001("The specified command is not recognized"),
+
+ /** The specified function is not recognized. */
+ SHELL_0002("The specified function is not recognized"),
+
+ /** An error has occurred when parsing options. */
+ SHELL_0003("An error has occurred when parsing options"),
+
+ /** Unable to resolve the variables. */
+ SHELL_0004("Unable to resolve the variables"),
+
+ /** We're not able to get user input */
+ SHELL_0005("Can't get user input"),
+
+ /** There occurred exception on server side **/
+ SHELL_0006("Server has returned exception"),
+
+ /** Command not compatible with batch mode */
+ SHELL_0007("Command not compatible with batch mode"),
+
+ /** Job Submission : Cannot sleep */
+ SHELL_0008("Cannot sleep"),
+
+ ;
+
+ private final String message;
+
+ private ShellError(String message) {
+ this.message = message;
+ }
+
+ public String getCode() {
+ return name();
+ }
+
+ public String getMessage() {
+ return message;
+ }
+}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/21c1207b/shell/src/main/java/org/apache/sqoop/shell/utils/FormDisplayer.java
----------------------------------------------------------------------
diff --git a/shell/src/main/java/org/apache/sqoop/shell/utils/FormDisplayer.java b/shell/src/main/java/org/apache/sqoop/shell/utils/FormDisplayer.java
new file mode 100644
index 0000000..56e0b4e
--- /dev/null
+++ b/shell/src/main/java/org/apache/sqoop/shell/utils/FormDisplayer.java
@@ -0,0 +1,249 @@
+/**
+ * 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.shell.utils;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.sqoop.model.MAccountableEntity;
+import org.apache.sqoop.model.MBooleanInput;
+import org.apache.sqoop.model.MConnection;
+import org.apache.sqoop.model.MEnumInput;
+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.MIntegerInput;
+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.apache.sqoop.shell.core.Constants;
+import org.apache.sqoop.validation.Status;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.ResourceBundle;
+
+import static org.apache.sqoop.shell.ShellEnvironment.*;
+
+/**
+ * Convenience static methods for displaying form related information
+ */
+public final class FormDisplayer {
+
+ public static void displayFormMetadataDetails(MFramework framework,
+ ResourceBundle bundle) {
+ print(" %s: ", resourceString(Constants.RES_FORMDISPLAYER_SUPPORTED_JOBTYPE));
+ println(framework.getAllJobsForms().keySet().toString());
+
+ displayFormsMetadata(
+ framework.getConnectionForms().getForms(),
+ resourceString(Constants.RES_FORMDISPLAYER_CONNECTION),
+ bundle);
+
+ for (MJobForms jobForms : framework.getAllJobsForms().values()) {
+ print(" %s ", resourceString(Constants.RES_FORMDISPLAYER_FORM_JOBTYPE));
+ print(jobForms.getType().name());
+ println(":");
+
+ displayFormsMetadata(jobForms.getForms(), resourceString(Constants.RES_FORMDISPLAYER_JOB), bundle);
+ }
+ }
+
+ public static void displayFormsMetadata(List<MForm> forms,
+ String type,
+ ResourceBundle bundle) {
+ Iterator<MForm> fiter = forms.iterator();
+ int findx = 1;
+ while (fiter.hasNext()) {
+ print(" ");
+ print(type);
+ print(" %s ", resourceString(Constants.RES_FORMDISPLAYER_FORM));
+ print(findx++);
+ println(":");
+
+ MForm form = fiter.next();
+ print(" %s: ", resourceString(Constants.RES_FORMDISPLAYER_NAME));
+ println(form.getName());
+
+ // Label
+ print(" %s: ", resourceString(Constants.RES_FORMDISPLAYER_LABEL));
+ println(bundle.getString(form.getLabelKey()));
+
+ // Help text
+ print(" %s: ", resourceString(Constants.RES_FORMDISPLAYER_HELP));
+ println(bundle.getString(form.getHelpKey()));
+
+ List<MInput<?>> inputs = form.getInputs();
+ Iterator<MInput<?>> iiter = inputs.iterator();
+ int iindx = 1;
+ while (iiter.hasNext()) {
+ print(" %s ", resourceString(Constants.RES_FORMDISPLAYER_INPUT));
+ print(iindx++);
+ println(":");
+
+ MInput<?> input = iiter.next();
+ print(" %s: ", resourceString(Constants.RES_FORMDISPLAYER_NAME));
+ println(input.getName());
+ print(" %s: ", resourceString(Constants.RES_FORMDISPLAYER_LABEL));
+ println(bundle.getString(input.getLabelKey()));
+ print(" %s: ", resourceString(Constants.RES_FORMDISPLAYER_HELP));
+ println(bundle.getString(input.getHelpKey()));
+ print(" %s: ", resourceString(Constants.RES_FORMDISPLAYER_TYPE));
+ println(input.getType());
+ print(" %s: ", resourceString(Constants.RES_FORMDISPLAYER_SENSITIVE));
+ println(input.isSensitive());
+ if (input.getType() == MInputType.STRING) {
+ print(" %s: ", resourceString(Constants.RES_FORMDISPLAYER_SIZE));
+ println(((MStringInput)input).getMaxLength());
+ } else if(input.getType() == MInputType.ENUM) {
+ print(" %s: ", resourceString(Constants.RES_FORMDISPLAYER_POSSIBLE_VALUES));
+ println(StringUtils.join(((MEnumInput)input).getValues(), ","));
+ }
+ }
+ }
+ }
+
+ public static void displayForms(List<MForm> forms, ResourceBundle bundle) {
+ for(MForm form : forms) {
+ displayForm(form, bundle);
+ }
+ }
+
+ /**
+ * Method prints the warning message of ACCEPTABLE status
+ * @param entity - connection or job instance
+ */
+ public static void displayFormWarning(MAccountableEntity entity) {
+ List<MForm> formList = new ArrayList<MForm>();
+ boolean showMessage = true;
+ if (entity instanceof MConnection) {
+ MConnection connection = (MConnection) entity;
+ formList.addAll(connection.getConnectorPart().getForms());
+ formList.addAll(connection.getFrameworkPart().getForms());
+ } else if(entity instanceof MJob) {
+ MJob job = (MJob) entity;
+ formList.addAll(job.getConnectorPart().getForms());
+ formList.addAll(job.getFrameworkPart().getForms());
+ }
+ for(MForm form : formList) {
+ if(form.getValidationStatus() == Status.ACCEPTABLE) {
+ if(showMessage) {
+ print("\n@|yellow %s|@\n", resourceString(Constants.RES_FORMDISPLAYER_FORM_WARNING));
+ showMessage = false;
+ }
+ FormFiller.warningMessage(form.getValidationMessage());
+ }
+ }
+ }
+
+ private static void displayForm(MForm form, ResourceBundle bundle) {
+ print(" ");
+ println(bundle.getString(form.getLabelKey()));
+
+ for (MInput<?> input : form.getInputs()) {
+ print(" ");
+ print(bundle.getString(input.getLabelKey()));
+ print(": ");
+ if(!input.isEmpty()) {
+ if (input.isSensitive()) {
+ print("(%s)", resourceString(Constants.RES_FORMDISPLAYER_INPUT_SENSITIVE));
+ } else {
+ // Based on the input type, let's perform specific load
+ switch (input.getType()) {
+ case STRING:
+ displayInputString((MStringInput) input);
+ break;
+ case INTEGER:
+ displayInputInteger((MIntegerInput) input);
+ break;
+ case BOOLEAN:
+ displayInputBoolean((MBooleanInput) input);
+ break;
+ case MAP:
+ displayInputMap((MMapInput) input);
+ break;
+ case ENUM:
+ displayInputEnum((MEnumInput) input);
+ break;
+ default:
+ print("\n%s " + input.getType(), resourceString(Constants.RES_FORMDISPLAYER_UNSUPPORTED_DATATYPE));
+ return;
+ }
+ }
+ }
+ println("");
+ }
+ }
+
+ /**
+ * Display content of String input.
+ *
+ * @param input String input
+ */
+ private static void displayInputString(MStringInput input) {
+ print(input.getValue());
+ }
+
+ /**
+ * Display content of Integer input.
+ *
+ * @param input Integer input
+ */
+ private static void displayInputInteger(MIntegerInput input) {
+ print(input.getValue());
+ }
+
+ /**
+ * Display content of Boolean input.
+ *
+ * @param input Boolean input
+ */
+ private static void displayInputBoolean(MBooleanInput input) {
+ print(input.getValue());
+ }
+
+ /**
+ * Display content of Map input
+ *
+ * @param input Map input
+ */
+ private static void displayInputMap(MMapInput input) {
+ for(Map.Entry<String, String> entry : input.getValue().entrySet()) {
+ println();
+ print(" ");
+ print(entry.getKey());
+ print(" = ");
+ print(entry.getValue());
+ }
+ }
+
+ /**
+ * Display content of Enum input
+ *
+ * @param input Enum input
+ */
+ private static void displayInputEnum(MEnumInput input) {
+ print(input.getValue());
+ }
+
+ private FormDisplayer() {
+ // Do not instantiate
+ }
+}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/21c1207b/shell/src/main/java/org/apache/sqoop/shell/utils/FormFiller.java
----------------------------------------------------------------------
diff --git a/shell/src/main/java/org/apache/sqoop/shell/utils/FormFiller.java b/shell/src/main/java/org/apache/sqoop/shell/utils/FormFiller.java
new file mode 100644
index 0000000..9bc0b93
--- /dev/null
+++ b/shell/src/main/java/org/apache/sqoop/shell/utils/FormFiller.java
@@ -0,0 +1,566 @@
+/**
+ * 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.shell.utils;
+
+import jline.ConsoleReader;
+import org.apache.sqoop.model.MBooleanInput;
+import org.apache.sqoop.model.MConnection;
+import org.apache.sqoop.model.MEnumInput;
+import org.apache.sqoop.model.MForm;
+import org.apache.sqoop.model.MInput;
+import org.apache.sqoop.model.MIntegerInput;
+import org.apache.sqoop.model.MMapInput;
+import org.apache.sqoop.model.MJob;
+import org.apache.sqoop.model.MStringInput;
+import org.apache.sqoop.model.MValidatedElement;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.ResourceBundle;
+
+import static org.apache.sqoop.shell.ShellEnvironment.*;
+
+/**
+ * Convenient methods for retrieving user input.
+ */
+public final class FormFiller {
+
+ /**
+ * Internal input that will be reused for loading names for connection and
+ * job objects.
+ */
+ private static MStringInput nameInput = new MStringInput("object-name", false, (short)25);
+
+ /**
+ * Fill job object based on user input.
+ *
+ * @param reader Associated console reader object
+ * @param job Job that user is suppose to fill in
+ * @param connectorBundle Connector resource bundle
+ * @param frameworkBundle Framework resource bundle
+ * @return True if we filled all inputs, false if user has stopped processing
+ * @throws IOException
+ */
+ public static boolean fillJob(ConsoleReader reader,
+ MJob job,
+ ResourceBundle connectorBundle,
+ ResourceBundle frameworkBundle)
+ throws IOException {
+
+ job.setName(getName(reader, job.getName()));
+
+ // Fill in data from user
+ return fillForms(reader,
+ job.getConnectorPart().getForms(),
+ connectorBundle,
+ job.getFrameworkPart().getForms(),
+ frameworkBundle);
+ }
+
+ /**
+ * Fill connection object based on user input.
+ *
+ * @param reader Associated console reader object
+ * @param connection Connection that user is suppose to fill in
+ * @param connectorBundle Connector resource bundle
+ * @param frameworkBundle Framework resouce bundle
+ * @return True if we filled all inputs, false if user has stopped processing
+ * @throws IOException
+ */
+ public static boolean fillConnection(ConsoleReader reader,
+ MConnection connection,
+ ResourceBundle connectorBundle,
+ ResourceBundle frameworkBundle)
+ throws IOException {
+
+ connection.setName(getName(reader, connection.getName()));
+
+ // Fill in data from user
+ return fillForms(reader,
+ connection.getConnectorPart().getForms(),
+ connectorBundle,
+ connection.getFrameworkPart().getForms(),
+ frameworkBundle);
+ }
+
+ public static boolean fillForms(ConsoleReader reader,
+ List<MForm> connectorForms,
+ ResourceBundle connectorBundle,
+ List<MForm> frameworkForms,
+ ResourceBundle frameworkBundle
+ ) throws IOException {
+
+
+ // Query connector forms
+ if(!fillForms(connectorForms, reader, connectorBundle)) {
+ return false;
+ }
+
+ // Query framework forms
+ if(!fillForms(frameworkForms, reader, frameworkBundle)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ public static boolean fillForms(List<MForm> forms,
+ ConsoleReader reader,
+ ResourceBundle bundle)
+ throws IOException {
+ for (MForm form : forms) {
+ if(!fillForm(form, reader, bundle)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public static boolean fillForm(MForm form,
+ ConsoleReader reader,
+ ResourceBundle bundle) throws IOException {
+ println("");
+ println(bundle.getString(form.getLabelKey()));
+
+ // Print out form validation
+ printValidationMessage(form);
+ println("");
+
+ for (MInput input : form.getInputs()) {
+ if(!fillInput(input, reader, bundle)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public static boolean fillInput(MInput input,
+ ConsoleReader reader,
+ ResourceBundle bundle) throws IOException {
+ // Print out validation
+ printValidationMessage(input);
+
+ // Based on the input type, let's perform specific load
+ switch (input.getType()) {
+ case STRING:
+ return fillInputString((MStringInput) input, reader, bundle);
+ case INTEGER:
+ return fillInputInteger((MIntegerInput) input, reader, bundle);
+ case BOOLEAN:
+ return fillInputBoolean((MBooleanInput) input, reader, bundle);
+ case MAP:
+ return fillInputMap((MMapInput) input, reader, bundle);
+ case ENUM:
+ return fillInputEnum((MEnumInput) input, reader, bundle);
+ default:
+ println("Unsupported data type " + input.getType());
+ return true;
+ }
+ }
+
+ /**
+ * Load user input for enum type.
+ *
+ * Print out numbered list of all available options and let user choose one
+ * item from that.
+ *
+ * @param input Input that we should read or edit
+ * @param reader Associated console reader
+ * @param bundle Resource bundle
+ * @return True if user with to continue with loading addtional inputs
+ * @throws IOException
+ */
+ private static boolean fillInputEnum(MEnumInput input,
+ ConsoleReader reader,
+ ResourceBundle bundle)
+ throws IOException {
+ // Prompt in enum case
+ println(bundle.getString(input.getLabelKey()) + ": ");
+
+ // Indexes
+ int i = -1;
+ int lastChoice = -1;
+
+ // Print out all values as a numbered list
+ for(String value : input.getValues()) {
+ i++;
+
+ println(" " + i + " : " + value);
+
+ // Only show last choice if not sensitive
+ if(!input.isEmpty() && value.equals(input.getValue()) && !input.isSensitive()) {
+ lastChoice = i;
+ }
+ }
+
+ // Prompt
+ reader.printString("Choose: ");
+
+ // Fill previously filled index when available
+ if(lastChoice != -1) {
+ reader.putString(Integer.toString(lastChoice));
+ }
+
+ reader.flushConsole();
+ String userTyped;
+ if(input.isSensitive()) {
+ userTyped = reader.readLine('*');
+ } else {
+ userTyped = reader.readLine();
+ }
+
+ if (userTyped == null) {
+ return false;
+ } else if (userTyped.isEmpty()) {
+ input.setEmpty();
+ } else {
+ Integer index;
+ try {
+ index = Integer.valueOf(userTyped);
+
+ if(index < 0 || index >= input.getValues().length) {
+ errorMessage("Invalid index");
+ return fillInputEnum(input, reader, bundle);
+ }
+
+ input.setValue(input.getValues()[index]);
+ } catch (NumberFormatException ex) {
+ errorMessage("Input is not valid integer number");
+ return fillInputEnum(input, reader, bundle);
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Load user input for map type.
+ *
+ * This implementation will load one map entry at the time. Current flows is
+ * as follows: if user did not enter anything (empty input) finish loading
+ * and return from function. If user specified input with equal sign (=),
+ * lets add new key value pair. Otherwise consider entire input as a key name
+ * and try to remove it from the map.
+ *
+ * Please note that following code do not supports equal sign in property
+ * name. It's however perfectly fine to have equal sign in value.
+ *
+ * @param input Input that we should read or edit
+ * @param reader Associated console reader
+ * @param bundle Resource bundle
+ * @return True if user wish to continue with loading additional inputs
+ * @throws IOException
+ */
+ private static boolean fillInputMap(MMapInput input,
+ ConsoleReader reader,
+ ResourceBundle bundle)
+ throws IOException {
+ // Special prompt in Map case
+ println(bundle.getString(input.getLabelKey()) + ": ");
+
+ // Internal loading map
+ Map<String, String> values = input.getValue();
+ if(values == null) {
+ values = new HashMap<String, String>();
+ }
+
+ String userTyped;
+
+ while(true) {
+ // Print all current items in each iteration
+ // However do not printout if this input contains sensitive information.
+ println("There are currently " + values.size() + " values in the map:");
+ if (!input.isSensitive()) {
+ for(Map.Entry<String, String> entry : values.entrySet()) {
+ println(entry.getKey() + " = " + entry.getValue());
+ }
+ }
+
+ // Special prompt for Map entry
+ reader.printString("entry# ");
+ reader.flushConsole();
+
+ if(input.isSensitive()) {
+ userTyped = reader.readLine('*');
+ } else {
+ userTyped = reader.readLine();
+ }
+
+ if(userTyped == null) {
+ // Finish loading and return back to Sqoop shell
+ return false;
+ } else if(userTyped.isEmpty()) {
+ // User has finished loading data to Map input, either set input empty
+ // if there are no entries or propagate entries to the input
+ if(values.size() == 0) {
+ input.setEmpty();
+ } else {
+ input.setValue(values);
+ }
+ return true;
+ } else {
+ // User has specified regular input, let's check if it contains equals
+ // sign. Save new entry (or update existing one) if it does. Otherwise
+ // try to remove entry that user specified.
+ if(userTyped.contains("=")) {
+ String []keyValue = userTyped.split("=", 2);
+ values.put(handleUserInput(keyValue[0]), handleUserInput(keyValue[1]));
+ } else {
+ String key = handleUserInput(userTyped);
+ if(values.containsKey(key)) {
+ values.remove(key);
+ } else {
+ errorMessage("Don't know what to do with " + userTyped);
+ }
+ }
+ }
+
+ }
+ }
+
+ /**
+ * Handle special cases in user input.
+ *
+ * Preserve null and empty values, remove whitespace characters before and
+ * after loaded string and de-quote the string if it's quoted (to preserve
+ * spaces for example).
+ *
+ * @param input String loaded from user
+ * @return Unquoted transformed string
+ */
+ private static String handleUserInput(String input) {
+ // Preserve null and empty values
+ if(input == null) {
+ return null;
+ }
+ if(input.isEmpty()) {
+ return input;
+ }
+
+ // Removes empty characters at the begging and end of loaded string
+ input = input.trim();
+
+ int lastIndex = input.length() - 1;
+ char first = input.charAt(0);
+ char last = input.charAt(lastIndex);
+
+ // Remove quoting if present
+ if(first == '\'' && last == '\'') {
+ input = input.substring(1, lastIndex);
+ } else if(first == '"' && last == '"') {
+ input = input.substring(1, lastIndex);
+ }
+
+ // Return final string
+ return input;
+ }
+
+ private static boolean fillInputInteger(MIntegerInput input,
+ ConsoleReader reader,
+ ResourceBundle bundle)
+ throws IOException {
+ generatePrompt(reader, bundle, input);
+
+ // Fill already filled data when available
+ // However do not printout if this input contains sensitive information.
+ if(!input.isEmpty() && !input.isSensitive()) {
+ reader.putString(input.getValue().toString());
+ }
+
+ // Get the data
+ String userTyped;
+ if(input.isSensitive()) {
+ userTyped = reader.readLine('*');
+ } else {
+ userTyped = reader.readLine();
+ }
+
+ if (userTyped == null) {
+ return false;
+ } else if (userTyped.isEmpty()) {
+ input.setEmpty();
+ } else {
+ Integer value;
+ try {
+ value = Integer.valueOf(userTyped);
+ input.setValue(value);
+ } catch (NumberFormatException ex) {
+ errorMessage("Input is not valid integer number");
+ return fillInputInteger(input, reader, bundle);
+ }
+
+ input.setValue(Integer.valueOf(userTyped));
+ }
+
+ return true;
+ }
+
+ /**
+ * Load string input from the user.
+ *
+ * @param input Input that we should load in
+ * @param reader Associated console reader
+ * @param bundle Resource bundle for this input
+ * @return
+ * @throws IOException
+ */
+ public static boolean fillInputString(MStringInput input,
+ ConsoleReader reader,
+ ResourceBundle bundle)
+ throws IOException {
+ generatePrompt(reader, bundle, input);
+
+ // Fill already filled data when available
+ // However do not printout if this input contains sensitive information.
+ if(!input.isEmpty() && !input.isSensitive()) {
+ reader.putString(input.getValue());
+ }
+
+ // Get the data
+ String userTyped;
+ if(input.isSensitive()) {
+ userTyped = reader.readLine('*');
+ } else {
+ userTyped = reader.readLine();
+ }
+
+ if (userTyped == null) {
+ // Propagate end of loading process
+ return false;
+ } else if (userTyped.isEmpty()) {
+ // Empty input in case that nothing was given
+ input.setEmpty();
+ } else {
+ // Set value that user has entered
+ input.setValue(userTyped);
+
+ // Check that it did not exceeds maximal allowance for given input
+ if(userTyped.length() > input.getMaxLength()) {
+ errorMessage("Size of input exceeds allowance for this input"
+ + " field. Maximal allowed size is " + input.getMaxLength());
+ return fillInputString(input, reader, bundle);
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Load boolean input from the user.
+ *
+ * @param input Input that we should load in
+ * @param reader Associated console reader
+ * @param bundle Resource bundle for this input
+ * @return
+ * @throws IOException
+ */
+ public static boolean fillInputBoolean(MBooleanInput input,
+ ConsoleReader reader,
+ ResourceBundle bundle)
+ throws IOException {
+ generatePrompt(reader, bundle, input);
+
+ // Fill already filled data when available
+ // However do not printout if this input contains sensitive information.
+ if(!input.isEmpty() && !input.isSensitive()) {
+ reader.putString(input.getValue().toString());
+ }
+
+ // Get the data
+ String userTyped;
+ if(input.isSensitive()) {
+ userTyped = reader.readLine('*');
+ } else {
+ userTyped = reader.readLine();
+ }
+
+ if (userTyped == null) {
+ // Propagate end of loading process
+ return false;
+ } else if (userTyped.isEmpty()) {
+ // Empty input in case that nothing was given
+ input.setEmpty();
+ } else {
+ // Set value that user has entered
+ input.setValue(Boolean.valueOf(userTyped));
+ }
+
+ return true;
+ }
+
+ public static void generatePrompt(ConsoleReader reader,
+ ResourceBundle bundle,
+ MInput input)
+ throws IOException {
+ reader.printString(bundle.getString(input.getLabelKey()) + ": ");
+ reader.flushConsole();
+ }
+
+ public static String getName(ConsoleReader reader,
+ String name) throws IOException {
+ if(name == null) {
+ nameInput.setEmpty();
+ } else {
+ nameInput.setValue(name);
+ }
+
+ fillInputString(nameInput, reader, getResourceBundle());
+
+ return nameInput.getValue();
+ }
+
+ /**
+ * Print validation message in cases that it's not in state "FINE"
+ *
+ * @param element Validated element
+ */
+ public static void printValidationMessage(MValidatedElement element) {
+ switch (element.getValidationStatus()) {
+ case UNACCEPTABLE:
+ errorMessage(element.getValidationMessage());
+ break;
+ case ACCEPTABLE:
+ warningMessage(element.getValidationMessage());
+ break;
+ default:
+ // Simply ignore all other states for the moment
+ break;
+ }
+ }
+
+ public static void errorMessage(String message) {
+ println("Error message: @|red " + message + " |@");
+ }
+
+ public static void warningMessage(String message) {
+ println("Warning message: @|yellow " + message + " |@");
+ }
+
+ public static void errorIntroduction() {
+ println();
+ println("@|red There are issues with entered data, please revise your input:|@");
+ }
+
+ private FormFiller() {
+ // Do not instantiate
+ }
+}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/21c1207b/shell/src/main/java/org/apache/sqoop/shell/utils/SubmissionDisplayer.java
----------------------------------------------------------------------
diff --git a/shell/src/main/java/org/apache/sqoop/shell/utils/SubmissionDisplayer.java b/shell/src/main/java/org/apache/sqoop/shell/utils/SubmissionDisplayer.java
new file mode 100644
index 0000000..1f61fb2
--- /dev/null
+++ b/shell/src/main/java/org/apache/sqoop/shell/utils/SubmissionDisplayer.java
@@ -0,0 +1,148 @@
+/**
+ * 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.shell.utils;
+
+import org.apache.sqoop.model.MSubmission;
+import org.apache.sqoop.shell.core.Constants;
+import org.apache.sqoop.submission.SubmissionStatus;
+import org.apache.sqoop.submission.counter.Counter;
+import org.apache.sqoop.submission.counter.CounterGroup;
+import org.apache.sqoop.submission.counter.Counters;
+
+import java.text.SimpleDateFormat;
+
+import static org.apache.sqoop.shell.ShellEnvironment.*;
+
+/**
+ * Class used for displaying or printing the submission details
+ */
+public final class SubmissionDisplayer {
+
+ private final static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
+
+ /**
+ * On job submission, displays the initial job info
+ * @param submission
+ */
+ public static void displayHeader(MSubmission submission) {
+ println("@|bold "+ resourceString(Constants.RES_SUBMISSION_SUBMISSION_DETAIL) +"|@");
+
+ print(resourceString(Constants.RES_SUBMISSION_JOB_ID)+": ");
+ println(submission.getJobId());
+
+ print(resourceString(Constants.RES_SUBMISSION_SERVER_URL)+": ");
+ println(getServerUrl());
+
+ print(resourceString(Constants.RES_SUBMISSION_CREATION_DATE)+": ");
+ println(dateFormat.format(submission.getCreationDate()));
+
+ String externalId = submission.getExternalId();
+ if(externalId != null) {
+ print(resourceString(Constants.RES_SUBMISSION_EXTERNAL_ID)+": ");
+ println(externalId);
+
+ String externalLink = submission.getExternalLink();
+ if(externalLink != null) {
+ println("\t" + externalLink);
+ }
+ }
+
+ if(isVerbose() && submission.getConnectorSchema() != null) {
+ print(resourceString(Constants.RES_CONNECTOR_SCHEMA)+": ");
+ println(submission.getConnectorSchema());
+ }
+
+ if(isVerbose() && submission.getHioSchema() != null) {
+ print(resourceString(Constants.RES_HIO_SCHEMA)+": ");
+ println(submission.getHioSchema());
+ }
+ }
+
+ /**
+ * Displays the progress of the executing job
+ * @param submission
+ */
+ public static void displayProgress(MSubmission submission) {
+ StringBuilder sb = new StringBuilder();
+ if(submission.getStatus().isRunning()) {
+ sb.append(dateFormat.format(submission.getLastUpdateDate())+": @|green "+submission.getStatus()+ " |@");
+ double progress = submission.getProgress();
+ sb.append(" - ");
+ if(progress == -1) {
+ sb.append(resourceString(Constants.RES_SUBMISSION_PROGRESS_NOT_AVAIL));
+ } else {
+ sb.append(String.format("%.2f %%", progress * 100));
+ }
+ } else {
+ sb.append(dateFormat.format(submission.getLastUpdateDate())+": "+submission.getStatus());
+ }
+
+ println(sb.toString());
+ }
+
+ /**
+ * On successfull or error, method is invoked
+ * @param submission
+ */
+ public static void displayFooter(MSubmission submission) {
+ if (submission.getStatus().toString().equals(SubmissionStatus.SUCCEEDED.toString())) {
+ println(dateFormat.format(submission.getLastUpdateDate())+": @|green "+submission.getStatus()+ " |@");
+ Counters counters = submission.getCounters();
+ if (counters != null) {
+ println(resourceString(Constants.RES_SUBMISSION_COUNTERS) + ":");
+ for (CounterGroup group : counters) {
+ print("\t");
+ println(group.getName());
+ for (Counter counter : group) {
+ print("\t\t");
+ print(counter.getName());
+ print(": ");
+ println(counter.getValue());
+ }
+ }
+ println(resourceString(Constants.RES_SUBMISSION_EXECUTED_SUCCESS));
+ }
+ } else {
+ if (submission.getStatus().isFailure()) {
+ println(dateFormat.format(submission.getLastUpdateDate())+": @|red "+submission.getStatus()+ " |@");
+ } else {
+ println(dateFormat.format(submission.getLastUpdateDate())+": "+submission.getStatus());
+ }
+ // Exception handling
+ if (submission.getExceptionInfo() != null) {
+ print("@|red Exception: |@");
+ println(submission.getExceptionInfo());
+
+ if (isVerbose() && submission.getExceptionStackTrace() != null) {
+ print("@|bold Stack trace: |@");
+ println(submission.getExceptionStackTrace());
+ }
+ }
+ }
+ }
+
+ public static void displaySubmission(MSubmission submission) {
+ if(submission.getStatus().isFailure() || submission.getStatus().equals(SubmissionStatus.SUCCEEDED)) {
+ SubmissionDisplayer.displayHeader(submission);
+ SubmissionDisplayer.displayFooter(submission);
+ } else {
+ SubmissionDisplayer.displayHeader(submission);
+ SubmissionDisplayer.displayProgress(submission);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/sqoop/blob/21c1207b/shell/src/main/java/org/apache/sqoop/shell/utils/TableDisplayer.java
----------------------------------------------------------------------
diff --git a/shell/src/main/java/org/apache/sqoop/shell/utils/TableDisplayer.java b/shell/src/main/java/org/apache/sqoop/shell/utils/TableDisplayer.java
new file mode 100644
index 0000000..51030d0
--- /dev/null
+++ b/shell/src/main/java/org/apache/sqoop/shell/utils/TableDisplayer.java
@@ -0,0 +1,141 @@
+/**
+ * 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.shell.utils;
+
+import org.apache.commons.lang.StringUtils;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import static org.apache.sqoop.shell.ShellEnvironment.*;
+
+/**
+ * Display table based data
+ */
+public class TableDisplayer {
+
+ /**
+ * Display given columns in nice table structure to given IO object.
+ *
+ * @param headers List of headers
+ * @param columns Array of columns
+ */
+ public static void display(List<String> headers, List<String> ...columns) {
+ assert headers != null;
+ assert columns != null;
+ assert headers.size() == columns.length;
+
+ // Count of columns
+ int columnCount = headers.size();
+
+ // List of all maximal widths of each column
+ List<Integer> widths = new LinkedList<Integer>();
+ for(int i = 0; i < columnCount; i++) {
+ widths.add(getMaximalWidth(headers.get(i), columns[i]));
+ }
+
+ // First line is border
+ drawLine(widths);
+
+ // Print out header (text is centralised)
+ print("| ");
+ for(int i = 0 ; i < columnCount; i++) {
+ print(StringUtils.center(headers.get(i), widths.get(i), ' '));
+ print((i == columnCount -1) ? " |" : " | ");
+ }
+ println();
+
+ // End up header by border
+ drawLine(widths);
+
+ // Number of rows in the table
+ int rows = getMaximalRows(columns);
+
+ // Print out each row
+ for(int row = 0 ; row < rows; row++) {
+ print("| ");
+ for(int i = 0 ; i < columnCount; i++) {
+ print(StringUtils.rightPad(columns[i].get(row), widths.get(i), ' '));
+ print((i == columnCount -1) ? " |" : " | ");
+ }
+ println();
+ }
+
+ // End table by final border
+ drawLine(widths);
+ }
+
+ /**
+ * Draw border line
+ *
+ * @param widths List of widths of each column
+ */
+ private static void drawLine(List<Integer> widths) {
+ int last = widths.size() - 1;
+ print("+-");
+ for(int i = 0; i < widths.size(); i++) {
+ print(StringUtils.repeat("-", widths.get(i)));
+ print((i == last) ? "-+" : "-+-");
+ }
+ println();
+ }
+
+ /**
+ * Get maximal width for given column with it's associated header.
+ *
+ * @param header Associated header
+ * @param column All column values
+ * @return Maximal
+ */
+ private static int getMaximalWidth(String header, List<String> column) {
+ assert header != null;
+ assert column != null;
+
+ int max = header.length();
+
+ for(String value : column) {
+ if(value != null && value.length() > max) {
+ max = value.length();
+ }
+ }
+
+ return max;
+ }
+
+ /**
+ * Get maximal number of rows available in the column list
+ *
+ * @param columns Array with all column values
+ * @return
+ */
+ private static int getMaximalRows(List<String>... columns) {
+ int max = 0;
+
+ for(List<String> column : columns) {
+ if(column.size() > max) {
+ max = column.size();
+ }
+ }
+
+ return max;
+ }
+
+ private TableDisplayer() {
+ // Instantiation is prohibited
+ }
+}