You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@knox.apache.org by lm...@apache.org on 2020/01/16 16:27:57 UTC
[knox] branch master updated: KNOX-2128 - Custom DataSource and SQL
Commands for KnoxShell and KnoxShellTable (#231)
This is an automated email from the ASF dual-hosted git repository.
lmccay pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/knox.git
The following commit(s) were added to refs/heads/master by this push:
new 7e9a79d KNOX-2128 - Custom DataSource and SQL Commands for KnoxShell and KnoxShellTable (#231)
7e9a79d is described below
commit 7e9a79dd85de235841ada1e7bee986d9a8c9631a
Author: lmccay <lm...@apache.org>
AuthorDate: Thu Jan 16 11:27:48 2020 -0500
KNOX-2128 - Custom DataSource and SQL Commands for KnoxShell and KnoxShellTable (#231)
* initial commit
* Jackson annotations
* fix select command
* KNOX-2128 - Custom DataSource and SQL Commands for KnoxShell and KnoxShellTable
* fix knoxshell.sh to use APP_JAR for shellcheck error
* address review comments
* fixed FileLock use
* fix indentation in knoxshell.sh
* address redundant swing workaround code
* address review comments
* address review comments and persistence when dirs don't exist
---
.../main/resources/build-tools/spotbugs-filter.xml | 15 ++
gateway-shell-release/home/bin/knoxshell.sh | 2 +-
.../home/conf/knoxshell-log4j.properties | 2 +-
.../apache/knox/gateway/shell/KnoxDataSource.java | 73 ++++++++
.../org/apache/knox/gateway/shell/KnoxSession.java | 132 +++++++++++++++
.../java/org/apache/knox/gateway/shell/Shell.java | 8 +
.../shell/commands/AbstractKnoxShellCommand.java | 46 +++++
.../shell/commands/AbstractSQLCommandSupport.java | 185 +++++++++++++++++++++
.../knox/gateway/shell/commands/CSVCommand.java | 66 ++++++++
.../gateway/shell/commands/DataSourceCommand.java | 108 ++++++++++++
.../gateway/shell/commands/KnoxLoginDialog.java | 111 +++++++++++++
.../knox/gateway/shell/commands/LoginCommand.java | 58 +++++++
.../knox/gateway/shell/commands/SelectCommand.java | 178 ++++++++++++++++++++
.../knox/gateway/shell/commands/SwingUtils.java | 51 ++++++
.../apache/knox/gateway/shell/jdbc/JDBCUtils.java | 38 +++++
.../shell/table/JDBCKnoxShellTableBuilder.java | 23 +--
.../knox/gateway/shell/table/KnoxShellTable.java | 2 +-
.../gateway/shell/table/KnoxShellTableTest.java | 2 +-
18 files changed, 1082 insertions(+), 18 deletions(-)
diff --git a/build-tools/src/main/resources/build-tools/spotbugs-filter.xml b/build-tools/src/main/resources/build-tools/spotbugs-filter.xml
index 239fb57..37f4e4f 100644
--- a/build-tools/src/main/resources/build-tools/spotbugs-filter.xml
+++ b/build-tools/src/main/resources/build-tools/spotbugs-filter.xml
@@ -52,6 +52,21 @@ limitations under the License.
</Match>
<Match>
+ <Class name="org.apache.knox.gateway.shell.table.JDBCKnoxShellTableBuilder" />
+ <Bug pattern="SQL_INJECTION_JDBC" />
+ </Match>
+
+ <Match>
+ <Class name="org.apache.knox.gateway.shell.commands.SelectCommand" />
+ <Bug pattern="SQL_INJECTION_JDBC" />
+ </Match>
+
+ <Match>
+ <Class name="org.apache.knox.gateway.shell.commands.DataSourceCommand" />
+ <Bug pattern="SQL_INJECTION_JDBC" />
+ </Match>
+
+ <Match>
<Class name="~org.apache.hadoop.gateway..*" />
<Bug pattern="NM_SAME_SIMPLE_NAME_AS_SUPERCLASS" />
</Match>
diff --git a/gateway-shell-release/home/bin/knoxshell.sh b/gateway-shell-release/home/bin/knoxshell.sh
index 52f7a98..6f8a8fe 100755
--- a/gateway-shell-release/home/bin/knoxshell.sh
+++ b/gateway-shell-release/home/bin/knoxshell.sh
@@ -81,7 +81,7 @@ function main {
checkJava
buildAppJavaOpts
- $JAVA "${APP_JAVA_OPTS[@]}" -javaagent:"$APP_BIN_DIR"/../lib/aspectjweaver.jar -jar "$APP_JAR" "$@" || exit 1
+ $JAVA "${APP_JAVA_OPTS[@]}" -Dlog4j.configuration=conf/knoxshell-log4j.properties -javaagent:"$APP_BIN_DIR"/../lib/aspectjweaver.jar -cp "$APP_JAR":lib/* org.apache.knox.gateway.shell.Shell "$@" || exit 1
return 0
}
diff --git a/gateway-shell-release/home/conf/knoxshell-log4j.properties b/gateway-shell-release/home/conf/knoxshell-log4j.properties
index c7e1312..cac3d99 100644
--- a/gateway-shell-release/home/conf/knoxshell-log4j.properties
+++ b/gateway-shell-release/home/conf/knoxshell-log4j.properties
@@ -14,7 +14,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-app.log.dir=${launcher.dir}/../logs
+app.log.dir=logs
app.log.file=${launcher.name}.log
log4j.rootLogger=ERROR, drfa
diff --git a/gateway-shell/src/main/java/org/apache/knox/gateway/shell/KnoxDataSource.java b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/KnoxDataSource.java
new file mode 100644
index 0000000..b5db74f
--- /dev/null
+++ b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/KnoxDataSource.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.knox.gateway.shell;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class KnoxDataSource {
+ private String name;
+ private String connectStr;
+ private String driver;
+ private String authnType;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getConnectStr() {
+ return connectStr;
+ }
+
+ public void setConnectStr(String connectStr) {
+ this.connectStr = connectStr;
+ }
+
+ public String getDriver() {
+ return driver;
+ }
+
+ public void setDriver(String driver) {
+ this.driver = driver;
+ }
+
+ public String getAuthnType() {
+ return authnType;
+ }
+
+ public void setAuthnType(String authnType) {
+ this.authnType = authnType;
+ }
+
+ public KnoxDataSource(@JsonProperty("name") String name,
+ @JsonProperty("contectStr") String connectStr,
+ @JsonProperty("driver") String driver,
+ @JsonProperty("authnType") String authnType) {
+ this.name = name;
+ this.connectStr = connectStr;
+ this.driver = driver;
+ this.authnType = authnType;
+ }
+
+ public KnoxDataSource(String name, String connectStr, String driver) {
+ this(name, connectStr, driver, "none");
+ }
+}
diff --git a/gateway-shell/src/main/java/org/apache/knox/gateway/shell/KnoxSession.java b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/KnoxSession.java
index 5fa26c0..085a9a6 100644
--- a/gateway-shell/src/main/java/org/apache/knox/gateway/shell/KnoxSession.java
+++ b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/KnoxSession.java
@@ -17,9 +17,13 @@
*/
package org.apache.knox.gateway.shell;
+import com.fasterxml.jackson.core.JsonFactory;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
import com.sun.security.auth.callback.TextCallbackHandler;
import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
@@ -52,6 +56,7 @@ import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.ssl.SSLContexts;
import org.apache.knox.gateway.i18n.messages.MessagesFactory;
import org.apache.knox.gateway.shell.util.ClientTrustStoreHelper;
+import org.apache.knox.gateway.util.JsonUtils;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
@@ -71,7 +76,12 @@ import java.lang.reflect.Constructor;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
+import java.nio.channels.FileChannel;
+import java.nio.channels.OverlappingFileLockException;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
+import java.nio.file.StandardOpenOption;
import java.security.AccessController;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
@@ -83,6 +93,7 @@ import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.HashMap;
+import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.Callable;
@@ -129,6 +140,9 @@ public class KnoxSession implements Closeable {
ExecutorService executor;
Map<String, String> headers = new HashMap<>();
+ private static final String KNOXSQLHISTORIES_JSON = "knoxsqlhistories.json";
+ private static final String KNOXDATASOURCES_JSON = "knoxdatasources.json";
+
public Map<String, String> getHeaders() {
return headers;
}
@@ -570,6 +584,124 @@ public class KnoxSession implements Closeable {
return String.format(Locale.ROOT, "KnoxSession{base='%s'}", base);
}
+ /**
+ * Persist provided Map to a file within the {user.home}/.knoxshell directory
+ * @param <T>
+ * @param fileName of persisted file
+ * @param map to persist
+ */
+ public static <T> void persistToKnoxShell(String fileName, Map<String, List<T>> map) {
+ String s = JsonUtils.renderAsJsonString(map);
+ String home = System.getProperty("user.home");
+ try {
+ write(new File(
+ home + File.separator +
+ ".knoxshell" + File.separator + fileName),
+ s, StandardCharsets.UTF_8);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private static void write(File file, String s, Charset utf8) throws IOException {
+ synchronized(KnoxSession.class) {
+ // Ensure the parent directory exists...
+ // This will attempt to create all missing directories. No failures will occur if the directories already exist.
+ Files.createDirectories(file.toPath().getParent());
+ try (FileChannel channel = FileChannel.open(file.toPath(), StandardOpenOption.WRITE,
+ StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)) {
+ channel.tryLock();
+ FileUtils.write(file, s, utf8);
+ }
+ catch (OverlappingFileLockException e) {
+ System.out.println("Unable to acquire write lock for: " + file.getAbsolutePath());
+ }
+ }
+ }
+
+ public static void persistSQLHistory(Map<String, List<String>> sqlHistories) {
+ persistToKnoxShell(KNOXSQLHISTORIES_JSON, sqlHistories);
+ }
+
+ public static void persistDataSources(Map<String, List<KnoxDataSource>> datasources) {
+ persistToKnoxShell(KNOXDATASOURCES_JSON, datasources);
+ }
+
+ /**
+ * Load and return a map of datasource names to sql commands
+ * from the {user.home}/.knoxshell/knoxsqlhistories.json file.
+ * @return sqlHistory map
+ */
+ public static Map<String, List<String>> loadSQLHistories() throws IOException {
+ Map<String, List<String>> sqlHistories = null;
+ String home = System.getProperty("user.home");
+
+ File historyFile = new File(
+ home + File.separator +
+ ".knoxshell" + File.separator + KNOXSQLHISTORIES_JSON);
+ if (historyFile.exists()) {
+ String json = readFileToString(historyFile, "UTF8");
+ sqlHistories = (Map<String, List<String>>) getMapOfStringArrayListsFromJsonString(json);
+ }
+ return sqlHistories;
+ }
+
+ private static String readFileToString(File file, String s)
+ throws FileNotFoundException, IOException {
+ String content = null;
+
+ synchronized(KnoxSession.class) {
+ try (FileChannel channel = FileChannel.open(file.toPath(), StandardOpenOption.READ)) {
+ channel.tryLock(0L, Long.MAX_VALUE, true);
+ content = FileUtils.readFileToString(file, s);
+ }
+ catch (OverlappingFileLockException e) {
+ System.out.println("Unable to acquire write lock for: " + file.getAbsolutePath());
+ }
+ }
+
+ return content;
+ }
+
+ /**
+ * Load and return a map of datasource names to KnoxDataSource
+ * objects from the {user.home}/.knoxshell/knoxdatasources.json file.
+ * @return
+ */
+ public static Map<String, KnoxDataSource> loadDataSources() throws IOException {
+ Map<String, KnoxDataSource> datasources = null;
+ String home = System.getProperty("user.home");
+ String json = null;
+
+ File dsFile = new File(
+ home + File.separator +
+ ".knoxshell" + File.separator + KNOXDATASOURCES_JSON);
+ if (dsFile.exists()) {
+ json = readFileToString(dsFile, "UTF8");
+ datasources = getMapOfDataSourcesFromJsonString(json);
+ }
+
+ return datasources;
+ }
+
+ public static Map<String, List<String>> getMapOfStringArrayListsFromJsonString(String json) throws IOException {
+ Map<String, List<String>> obj = null;
+ JsonFactory factory = new JsonFactory();
+ ObjectMapper mapper = new ObjectMapper(factory);
+ TypeReference<Map<String, List<String>>> typeRef = new TypeReference<Map<String, List<String>>>() {};
+ obj = mapper.readValue(json, typeRef);
+ return obj;
+ }
+
+ public static Map<String, KnoxDataSource> getMapOfDataSourcesFromJsonString(String json) throws IOException {
+ Map<String, KnoxDataSource> obj = null;
+ JsonFactory factory = new JsonFactory();
+ ObjectMapper mapper = new ObjectMapper(factory);
+ TypeReference<Map<String, KnoxDataSource>> typeRef = new TypeReference<Map<String, KnoxDataSource>>() {};
+ obj = mapper.readValue(json, typeRef);
+ return obj;
+ }
+
private static final class JAASClientConfig extends Configuration {
private static final Configuration baseConfig = Configuration.getConfiguration();
diff --git a/gateway-shell/src/main/java/org/apache/knox/gateway/shell/Shell.java b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/Shell.java
index 62079c4..30c6fbb 100644
--- a/gateway-shell/src/main/java/org/apache/knox/gateway/shell/Shell.java
+++ b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/Shell.java
@@ -18,6 +18,10 @@
package org.apache.knox.gateway.shell;
import groovy.ui.GroovyMain;
+
+import org.apache.knox.gateway.shell.commands.CSVCommand;
+import org.apache.knox.gateway.shell.commands.DataSourceCommand;
+import org.apache.knox.gateway.shell.commands.SelectCommand;
import org.apache.knox.gateway.shell.hbase.HBase;
import org.apache.knox.gateway.shell.hdfs.Hdfs;
import org.apache.knox.gateway.shell.job.Job;
@@ -76,6 +80,10 @@ public class Shell {
for( String name : IMPORTS ) {
shell.execute( "import " + name );
}
+ // register custom groovysh commands
+ shell.register(new SelectCommand(shell));
+ shell.register(new DataSourceCommand(shell));
+ shell.register(new CSVCommand(shell));
shell.run( null );
}
}
diff --git a/gateway-shell/src/main/java/org/apache/knox/gateway/shell/commands/AbstractKnoxShellCommand.java b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/commands/AbstractKnoxShellCommand.java
new file mode 100644
index 0000000..3fa400e
--- /dev/null
+++ b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/commands/AbstractKnoxShellCommand.java
@@ -0,0 +1,46 @@
+/*
+ * 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.knox.gateway.shell.commands;
+
+import java.util.List;
+import org.codehaus.groovy.tools.shell.CommandSupport;
+import org.codehaus.groovy.tools.shell.Groovysh;
+
+public abstract class AbstractKnoxShellCommand extends CommandSupport {
+ static final String KNOXSQLHISTORY = "__knoxsqlhistory";
+ protected static final String KNOXDATASOURCES = "__knoxdatasources";
+
+ public AbstractKnoxShellCommand(Groovysh shell, String name, String shortcut) {
+ super(shell, name, shortcut);
+ }
+
+ protected String getBindingVariableNameForResultingTable(List<String> args) {
+ String variableName = null;
+ boolean nextOne = false;
+ for (String arg : args) {
+ if (nextOne) {
+ variableName = arg;
+ break;
+ }
+ if ("assign".equalsIgnoreCase(arg)) {
+ nextOne = true;
+ }
+ }
+ return variableName;
+ }
+}
\ No newline at end of file
diff --git a/gateway-shell/src/main/java/org/apache/knox/gateway/shell/commands/AbstractSQLCommandSupport.java b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/commands/AbstractSQLCommandSupport.java
new file mode 100644
index 0000000..0f7a5ab
--- /dev/null
+++ b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/commands/AbstractSQLCommandSupport.java
@@ -0,0 +1,185 @@
+/*
+ * 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.knox.gateway.shell.commands;
+
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.knox.gateway.shell.KnoxDataSource;
+import org.apache.knox.gateway.shell.KnoxSession;
+import org.apache.knox.gateway.shell.jdbc.JDBCUtils;
+import org.codehaus.groovy.tools.shell.Groovysh;
+
+public abstract class AbstractSQLCommandSupport extends AbstractKnoxShellCommand {
+
+ protected static final String KNOXDATASOURCES = "__knoxdatasources";
+ protected static final String KNOXDATASOURCE = "__knoxdatasource";
+ private static final Object KNOXDATASOURCE_CONNECTIONS = "__knoxdatasourceconnections";
+
+ public AbstractSQLCommandSupport(Groovysh shell, String name, String shortcut) {
+ super(shell, name, shortcut);
+ }
+
+ @SuppressWarnings("unchecked")
+ protected Connection getConnectionFromSession(KnoxDataSource ds) {
+ HashMap<String, Connection> connections =
+ (HashMap<String, Connection>) getVariables()
+ .getOrDefault(KNOXDATASOURCE_CONNECTIONS,
+ new HashMap<String, Connection>());
+
+ Connection conn = connections.get(ds.getName());
+ return conn;
+ }
+
+ @SuppressWarnings("unchecked")
+ protected Connection getConnection(KnoxDataSource ds, String user, String pass) throws SQLException, Exception {
+ Connection conn = getConnectionFromSession(ds);
+ if (conn == null) {
+ if (user != null && pass != null) {
+ conn = JDBCUtils.createConnection(ds.getConnectStr(), user, pass);
+ }
+ else {
+ conn = JDBCUtils.createConnection(ds.getConnectStr(), null, null);
+
+ }
+ HashMap<String, Connection> connections =
+ (HashMap<String, Connection>) getVariables()
+ .getOrDefault(KNOXDATASOURCE_CONNECTIONS,
+ new HashMap<String, Connection>());
+ connections.put(ds.getName(), conn);
+ getVariables().put(KNOXDATASOURCE_CONNECTIONS, connections);
+ }
+ return conn;
+ }
+
+ protected void persistSQLHistory() {
+ Map<String, List<String>> sqlHistories =
+ (Map<String, List<String>>) getVariables().get(KNOXSQLHISTORY);
+ KnoxSession.persistSQLHistory(sqlHistories);
+ }
+
+ protected void persistDataSources() {
+ Map<String, List<KnoxDataSource>> datasources =
+ (Map<String, List<KnoxDataSource>>) getVariables().get(KNOXDATASOURCES);
+ KnoxSession.persistDataSources(datasources);
+ }
+
+ protected List<String> getSQLHistory(String dataSourceName) {
+ List<String> sqlHistory = null;
+ Map<String, List<String>> sqlHistories =
+ (Map<String, List<String>>) getVariables().get(KNOXSQLHISTORY);
+ if (sqlHistories == null) {
+ // check for persisted histories for known datasources
+ sqlHistories = loadSQLHistories();
+ if (sqlHistories == null || sqlHistories.isEmpty()) {
+ sqlHistories = new HashMap<>();
+ getVariables().put(KNOXSQLHISTORY, sqlHistories);
+ }
+ }
+ // get the history for the specific datasource
+ sqlHistory = sqlHistories.get(dataSourceName);
+ if (sqlHistory == null) {
+ sqlHistory = startSqlHistory(dataSourceName, sqlHistories);
+ }
+ return sqlHistory;
+ }
+
+ private List<String> startSqlHistory(String dataSourceName, Map<String, List<String>> sqlHistories) {
+ List<String> sqlHistory = new ArrayList<>();
+ sqlHistories.put(dataSourceName, sqlHistory);
+ return sqlHistory;
+ }
+
+ private Map<String, List<String>> loadSQLHistories() {
+ Map<String, List<String>> sqlHistories = null;
+ try {
+ sqlHistories = KnoxSession.loadSQLHistories();
+ if (sqlHistories != null) {
+ getVariables().put(KNOXSQLHISTORY, sqlHistories);
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return sqlHistories;
+ }
+
+ private Map<String, KnoxDataSource> loadDataSources() {
+ Map<String, KnoxDataSource> datasources = null;
+ try {
+ datasources = KnoxSession.loadDataSources();
+ if (datasources != null) {
+ getVariables().put(KNOXDATASOURCES, datasources);
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return datasources;
+ }
+
+ protected void addToSQLHistory(String dsName, String sql) {
+ List<String> sqlHistory = null;
+ if (sql != null && !sql.isEmpty()) {
+ sqlHistory = getSQLHistory(dsName);
+ if (sqlHistory != null) {
+ sqlHistory.add(sql);
+ }
+ }
+
+ if (sqlHistory != null && sqlHistory.size() > 20) {
+ sqlHistory.remove(0);
+ }
+ persistSQLHistory();
+ }
+
+ protected void addToSQLHistory(List<String> sqlHistory, String sql) {
+ if (sql != null && !sql.isEmpty()) {
+ sqlHistory.add(sql);
+ }
+
+ if (sqlHistory.size() > 20) {
+ sqlHistory.remove(0);
+ }
+ persistSQLHistory();
+ }
+
+ protected void removeFromSQLHistory(String dsName) {
+ Map<String, List<String>> sqlHistories =
+ (Map<String, List<String>>) getVariables().get(KNOXSQLHISTORY);
+ sqlHistories.remove(dsName);
+ persistSQLHistory();
+ }
+
+ protected Map<String, KnoxDataSource> getDataSources() {
+ Map<String, KnoxDataSource> datasources = (Map<String, KnoxDataSource>) getVariables().get(KNOXDATASOURCES);
+ if (datasources == null) {
+ datasources = loadDataSources();
+ if (datasources != null) {
+ getVariables().put(KNOXDATASOURCES, datasources);
+ }
+ else {
+ datasources = new HashMap<>();
+ }
+ }
+ return datasources;
+ }
+}
\ No newline at end of file
diff --git a/gateway-shell/src/main/java/org/apache/knox/gateway/shell/commands/CSVCommand.java b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/commands/CSVCommand.java
new file mode 100644
index 0000000..22aad2c
--- /dev/null
+++ b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/commands/CSVCommand.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.knox.gateway.shell.commands;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.knox.gateway.shell.table.KnoxShellTable;
+import org.codehaus.groovy.tools.shell.Groovysh;
+
+public class CSVCommand extends AbstractKnoxShellCommand {
+ private boolean withHeaders;
+ private String url;
+
+ public CSVCommand(Groovysh shell) {
+ super(shell, ":CSV", ":csv");
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Object execute(List<String> args) {
+ KnoxShellTable table = null;
+ String bindVariableName = null;
+ if (!args.isEmpty()) {
+ bindVariableName = getBindingVariableNameForResultingTable(args);
+ }
+ if (args.get(0).contentEquals("withHeaders")) {
+ withHeaders = true;
+ url = args.get(1);
+ }
+ else {
+ url = args.get(0);
+ }
+
+ try {
+ if (withHeaders) {
+ table = KnoxShellTable.builder().csv().withHeaders().url(url);
+ }
+ else {
+ table = KnoxShellTable.builder().csv().url(url);
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ if (table != null && bindVariableName != null) {
+ getVariables().put(bindVariableName, table);
+ }
+ return table;
+ }
+
+}
diff --git a/gateway-shell/src/main/java/org/apache/knox/gateway/shell/commands/DataSourceCommand.java b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/commands/DataSourceCommand.java
new file mode 100644
index 0000000..084aaa4
--- /dev/null
+++ b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/commands/DataSourceCommand.java
@@ -0,0 +1,108 @@
+/*
+ * 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.knox.gateway.shell.commands;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.knox.gateway.shell.KnoxDataSource;
+import org.apache.knox.gateway.shell.table.KnoxShellTable;
+import org.codehaus.groovy.tools.shell.Groovysh;
+
+public class DataSourceCommand extends AbstractSQLCommandSupport {
+
+ public DataSourceCommand(Groovysh shell) {
+ super(shell, ":datasources", ":ds");
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Object execute(List<String> args) {
+ Map<String, KnoxDataSource> dataSources =
+ getDataSources();
+ if (args.isEmpty()) {
+ args.add("list");
+ }
+ if (args.get(0).equalsIgnoreCase("add")) {
+ KnoxDataSource ds = new KnoxDataSource(args.get(1),
+ args.get(2),
+ args.get(3),
+ args.get(4));
+ dataSources.put(ds.getName(), ds);
+ getVariables().put(KNOXDATASOURCES, dataSources);
+ persistDataSources();
+ }
+ else if (args.get(0).equalsIgnoreCase("remove")) {
+ if (dataSources == null || dataSources.isEmpty()) {
+ return "No datasources to remove.";
+ }
+ // if the removed datasource is currently selected, unselect it
+ dataSources.remove(args.get(1));
+ if (((String)getVariables().get(KNOXDATASOURCE)).equals(args.get(1))) {
+ System.out.println("unselecting datasource.");
+ getVariables().put(KNOXDATASOURCE, "");
+ getVariables().put(KNOXDATASOURCES, dataSources);
+ persistDataSources();
+ }
+ }
+ else if (args.get(0).equalsIgnoreCase("list")) {
+ // valid command no additional work needed though
+ }
+ else if(args.get(0).equalsIgnoreCase("select")) {
+ if (dataSources == null || dataSources.isEmpty()) {
+ return "No datasources to select from.";
+ }
+ if (dataSources.containsKey(args.get(1))) {
+ getVariables().put(KNOXDATASOURCE, args.get(1));
+ }
+ KnoxDataSource dsValue = dataSources.get(args.get(1));
+ KnoxShellTable datasource = new KnoxShellTable();
+ datasource.title("Knox DataSource Selected");
+ datasource.header("Name").header("Connect String").header("Driver").header("Authn Type");
+ datasource.row().value(dsValue.getName()).value(dsValue.getConnectStr()).value(dsValue.getDriver()).value(dsValue.getAuthnType());
+ return datasource;
+ }
+ else {
+ return "ERROR: unknown datasources command.";
+ }
+
+ return buildTable();
+ }
+
+ private KnoxShellTable buildTable() {
+ KnoxShellTable datasource = new KnoxShellTable();
+ datasource.title("Knox DataSources");
+ datasource.header("Name").header("Connect String").header("Driver").header("Authn Type");
+ @SuppressWarnings("unchecked")
+ Map<String, KnoxDataSource> dataSources =
+ (Map<String, KnoxDataSource>) getVariables().get(KNOXDATASOURCES);
+ if (dataSources != null && !dataSources.isEmpty()) {
+ for(KnoxDataSource dsValue : dataSources.values()) {
+ datasource.row().value(dsValue.getName()).value(dsValue.getConnectStr()).value(dsValue.getDriver()).value(dsValue.getAuthnType());
+ }
+ }
+ return datasource;
+ }
+
+ public static void main(String[] args) {
+ DataSourceCommand cmd = new DataSourceCommand(new Groovysh());
+ List<String> args2 = new ArrayList<>();
+ cmd.execute(args2);
+ }
+}
diff --git a/gateway-shell/src/main/java/org/apache/knox/gateway/shell/commands/KnoxLoginDialog.java b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/commands/KnoxLoginDialog.java
new file mode 100644
index 0000000..fba19ef
--- /dev/null
+++ b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/commands/KnoxLoginDialog.java
@@ -0,0 +1,111 @@
+/*
+ * 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.knox.gateway.shell.commands;
+
+import javax.swing.Box;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPasswordField;
+import javax.swing.JTextField;
+import org.apache.knox.gateway.shell.CredentialCollectionException;
+import org.apache.knox.gateway.shell.CredentialCollector;
+
+public class KnoxLoginDialog implements CredentialCollector {
+ public static final String COLLECTOR_TYPE = "LoginDialog";
+
+ public char[] pass;
+ public String username;
+ String name;
+ public boolean ok;
+
+ @Override
+ public void collect() throws CredentialCollectionException {
+ JLabel jl = new JLabel("Enter Your username: ");
+ JTextField juf = new JTextField(24);
+ JLabel jl2 = new JLabel("Enter Your password: ");
+ JPasswordField jpf = new JPasswordField(24);
+ Box box1 = Box.createHorizontalBox();
+ box1.add(jl);
+ box1.add(juf);
+ Box box2 = Box.createHorizontalBox();
+ box2.add(jl2);
+ box2.add(jpf);
+ Box box = Box.createVerticalBox();
+ box.add(box1);
+ box.add(box2);
+
+ // JDK-5018574 : Unable to set focus to another component in JOptionPane
+ SwingUtils.workAroundFocusIssue(juf);
+
+ int x = JOptionPane.showConfirmDialog(null, box,
+ "KnoxShell Login", JOptionPane.OK_CANCEL_OPTION);
+
+ if (x == JOptionPane.OK_OPTION) {
+ ok = true;
+ username = juf.getText();
+ pass = jpf.getPassword();
+ }
+ }
+
+ @Override
+ public String string() {
+ return new String(pass);
+ }
+
+ @Override
+ public char[] chars() {
+ return pass;
+ }
+
+ @Override
+ public byte[] bytes() {
+ return null;
+ }
+
+ @Override
+ public String type() {
+ return "dialog";
+ }
+
+ @Override
+ public String name() {
+ return name;
+ }
+
+ @Override
+ public void setPrompt(String prompt) {
+ }
+
+ @Override
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public static void main(String[] args) {
+ KnoxLoginDialog dlg = new KnoxLoginDialog();
+ try {
+ dlg.collect();
+ if (dlg.ok) {
+ System.out.println("username: " + dlg.username);
+ System.out.println("password: " + new String(dlg.pass));
+ }
+ } catch (CredentialCollectionException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/gateway-shell/src/main/java/org/apache/knox/gateway/shell/commands/LoginCommand.java b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/commands/LoginCommand.java
new file mode 100644
index 0000000..e532948
--- /dev/null
+++ b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/commands/LoginCommand.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.knox.gateway.shell.commands;
+
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.knox.gateway.shell.CredentialCollectionException;
+import org.apache.knox.gateway.shell.KnoxSession;
+import org.codehaus.groovy.tools.shell.CommandSupport;
+import org.codehaus.groovy.tools.shell.Groovysh;
+
+public class LoginCommand extends CommandSupport {
+
+ public LoginCommand(Groovysh shell) {
+ super(shell, ":login", ":lgn");
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Object execute(List<String> args) {
+ KnoxSession session = null;
+ KnoxLoginDialog dlg = new KnoxLoginDialog();
+ try {
+ dlg.collect();
+ if (dlg.ok) {
+ session = KnoxSession.login(args.get(0), dlg.username, new String(dlg.pass));
+ getVariables().put("__knoxsession", session);
+ }
+ } catch (CredentialCollectionException | URISyntaxException e) {
+ e.printStackTrace();
+ }
+ return "Session established for: " + args.get(0);
+ }
+
+ public static void main(String[] args) {
+ LoginCommand cmd = new LoginCommand(new Groovysh());
+ List<String> args2 = new ArrayList<>();
+ args2.add("https://localhost:8443/gateway");
+ cmd.execute(args2);
+ }
+}
diff --git a/gateway-shell/src/main/java/org/apache/knox/gateway/shell/commands/SelectCommand.java b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/commands/SelectCommand.java
new file mode 100644
index 0000000..d614cd1
--- /dev/null
+++ b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/commands/SelectCommand.java
@@ -0,0 +1,178 @@
+/*
+ * 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.knox.gateway.shell.commands;
+
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.net.URISyntaxException;
+import java.util.List;
+import java.util.Map;
+
+import javax.swing.Box;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+
+import org.apache.knox.gateway.shell.CredentialCollectionException;
+import org.apache.knox.gateway.shell.KnoxDataSource;
+import org.apache.knox.gateway.shell.table.KnoxShellTable;
+import org.codehaus.groovy.tools.shell.Groovysh;
+
+public class SelectCommand extends AbstractSQLCommandSupport implements KeyListener {
+
+ private static final String KNOXDATASOURCE = "__knoxdatasource";
+ private JTextArea sqlField;
+ private List<String> sqlHistory;
+ private int historyIndex = -1;
+
+ public SelectCommand(Groovysh shell) {
+ super(shell, ":SQL", ":sql");
+ }
+
+ @Override
+ public void keyPressed(KeyEvent event) {
+ int code = event.getKeyCode();
+ boolean setFromHistory = false;
+ if (sqlHistory != null && !sqlHistory.isEmpty()) {
+ if (historyIndex == -1) {
+ historyIndex = sqlHistory.size() + 1;
+ }
+ if (code == KeyEvent.VK_KP_UP ||
+ code == KeyEvent.VK_UP) {
+ if (historyIndex > 0) {
+ historyIndex -= 1;
+ }
+ setFromHistory = true;
+ }
+ else if (code == KeyEvent.VK_KP_DOWN ||
+ code == KeyEvent.VK_DOWN) {
+ if (historyIndex < sqlHistory.size() - 1) {
+ historyIndex += 1;
+ setFromHistory = true;
+ }
+ }
+ if (setFromHistory) {
+ sqlField.setText(sqlHistory.get(historyIndex));
+ sqlField.invalidate();
+ }
+ }
+ }
+
+ @Override
+ public void keyReleased(KeyEvent event) {
+ }
+
+ @Override
+ public void keyTyped(KeyEvent event) {
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Object execute(List<String> args) {
+ boolean ok = false;
+ String sql = "";
+ String bindVariableName = null;
+ KnoxShellTable table = null;
+
+ if (!args.isEmpty()) {
+ bindVariableName = getBindingVariableNameForResultingTable(args);
+ }
+
+ String dsName = (String) getVariables().get(KNOXDATASOURCE);
+ @SuppressWarnings("unchecked")
+ Map<String, KnoxDataSource> dataSources = getDataSources();
+ KnoxDataSource ds = null;
+ if (dsName == null || dsName.isEmpty()) {
+ if (dataSources == null || dataSources.isEmpty()) {
+ return "please configure a datasource with ':datasources add {name} {connectStr} {driver} {authntype: none|basic}'.";
+ }
+ else if (dataSources.size() == 1) {
+ dsName = (String) dataSources.keySet().toArray()[0];
+ }
+ else {
+ return "mulitple datasources configured. please disambiguate with ':datasources select {name}'.";
+ }
+ }
+
+ sqlHistory = getSQLHistory(dsName);
+ historyIndex = (sqlHistory != null && !sqlHistory.isEmpty()) ? sqlHistory.size() - 1 : -1;
+
+ ds = dataSources.get(dsName);
+ if (ds != null) {
+ JLabel jl = new JLabel("Query: ");
+ sqlField = new JTextArea(5,40);
+ sqlField.addKeyListener(this);
+ sqlField.setLineWrap(true);
+ JScrollPane scrollPane = new JScrollPane(sqlField);
+ Box box = Box.createHorizontalBox();
+ box.add(jl);
+ box.add(scrollPane);
+
+ // JDK-5018574 : Unable to set focus to another component in JOptionPane
+ SwingUtils.workAroundFocusIssue(sqlField);
+
+ int x = JOptionPane.showConfirmDialog(null, box,
+ "SQL Query Input", JOptionPane.OK_CANCEL_OPTION);
+
+ if (x == JOptionPane.OK_OPTION) {
+ ok = true;
+ sql = sqlField.getText();
+ addToSQLHistory(dsName, sql);
+ historyIndex = -1;
+ }
+
+ //KnoxShellTable.builder().jdbc().connect("jdbc:derby:codejava/webdb1").driver("org.apache.derby.jdbc.EmbeddedDriver").username("lmccay").pwd("xxxx").sql("SELECT * FROM book");
+ try {
+ if (ok) {
+ if (ds.getAuthnType().equalsIgnoreCase("none")) {
+ table = KnoxShellTable.builder().jdbc()
+ .connectTo(ds.getConnectStr())
+ .driver(ds.getDriver())
+ .sql(sql);
+ }
+ else if (ds.getAuthnType().equalsIgnoreCase("basic")) {
+ KnoxLoginDialog dlg = new KnoxLoginDialog();
+ try {
+ dlg.collect();
+ if (dlg.ok) {
+ table = KnoxShellTable.builder().jdbc()
+ .connectTo(ds.getConnectStr())
+ .driver(ds.getDriver())
+ .username(dlg.username)
+ .password(new String(dlg.pass))
+ .sql(sql);
+ }
+ } catch (CredentialCollectionException | URISyntaxException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ else {
+ return "please select a datasource via ':datasources select {name}'.";
+ }
+ if (table != null && bindVariableName != null) {
+ getVariables().put(bindVariableName, table);
+ }
+ return table;
+ }
+}
diff --git a/gateway-shell/src/main/java/org/apache/knox/gateway/shell/commands/SwingUtils.java b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/commands/SwingUtils.java
new file mode 100644
index 0000000..99bc1d3
--- /dev/null
+++ b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/commands/SwingUtils.java
@@ -0,0 +1,51 @@
+/*
+ * 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.knox.gateway.shell.commands;
+
+import java.awt.Component;
+import java.awt.Window;
+import java.awt.event.HierarchyEvent;
+import java.awt.event.HierarchyListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+
+import javax.swing.SwingUtilities;
+import javax.swing.text.JTextComponent;
+
+public class SwingUtils {
+
+ // JDK-5018574 : Unable to set focus to another component in JOptionPane
+ public static void workAroundFocusIssue(JTextComponent field) {
+ field.addHierarchyListener(new HierarchyListener() {
+ @Override
+ public void hierarchyChanged(HierarchyEvent e) {
+ final Component c = e.getComponent();
+ if (c.isShowing() && (e.getChangeFlags() &
+ HierarchyEvent.SHOWING_CHANGED) != 0) {
+ Window toplevel = SwingUtilities.getWindowAncestor(c);
+ toplevel.addWindowFocusListener(new WindowAdapter() {
+ @Override
+ public void windowGainedFocus(WindowEvent e) {
+ c.requestFocus();
+ }
+ });
+ }
+ }
+ });
+ }
+}
diff --git a/gateway-shell/src/main/java/org/apache/knox/gateway/shell/jdbc/JDBCUtils.java b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/jdbc/JDBCUtils.java
new file mode 100644
index 0000000..9b93553
--- /dev/null
+++ b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/jdbc/JDBCUtils.java
@@ -0,0 +1,38 @@
+/*
+ * 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.knox.gateway.shell.jdbc;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+
+import org.apache.commons.lang3.StringUtils;
+
+public class JDBCUtils {
+ public static Connection createConnection(String connectionUrl,
+ String username, String pass) throws SQLException {
+ Connection con = null;
+ if (StringUtils.isNotBlank(username) && pass != null) {
+ con = DriverManager.getConnection(connectionUrl, username, pass);
+ }
+ else {
+ con = DriverManager.getConnection(connectionUrl);
+ }
+ return con;
+ }
+}
diff --git a/gateway-shell/src/main/java/org/apache/knox/gateway/shell/table/JDBCKnoxShellTableBuilder.java b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/table/JDBCKnoxShellTableBuilder.java
index 0543044..3d1e69f 100644
--- a/gateway-shell/src/main/java/org/apache/knox/gateway/shell/table/JDBCKnoxShellTableBuilder.java
+++ b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/table/JDBCKnoxShellTableBuilder.java
@@ -19,14 +19,13 @@ package org.apache.knox.gateway.shell.table;
import java.io.IOException;
import java.sql.Connection;
-import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Locale;
-import org.apache.commons.lang3.StringUtils;
+import org.apache.knox.gateway.shell.jdbc.JDBCUtils;
public class JDBCKnoxShellTableBuilder extends KnoxShellTableBuilder {
@@ -42,15 +41,15 @@ public class JDBCKnoxShellTableBuilder extends KnoxShellTableBuilder {
return this;
}
- public String username() {
- return username;
- }
-
- public JDBCKnoxShellTableBuilder pwd(String pass) {
+ public JDBCKnoxShellTableBuilder password(String pass) {
this.pass = pass;
return this;
}
+ public String username() {
+ return username;
+ }
+
public String password() {
return pass;
}
@@ -110,11 +109,7 @@ public class JDBCKnoxShellTableBuilder extends KnoxShellTableBuilder {
}
private Connection createConnection() throws SQLException {
- if (StringUtils.isNotBlank(username) && pass != null) {
- return DriverManager.getConnection(connectionUrl, username, pass);
- } else {
- return DriverManager.getConnection(connectionUrl);
- }
+ return JDBCUtils.createConnection(connectionUrl, username, pass);
}
// added this as a private method so that KnoxShellTableHistoryAspect will not
@@ -132,7 +127,7 @@ public class JDBCKnoxShellTableBuilder extends KnoxShellTableBuilder {
this.table.header(metadata.getColumnName(i));
}
while (resultSet.next()) {
- table.row();
+ this.table.row();
for (int i = 1; i < colCount + 1; i++) {
try {
table.value(resultSet.getObject(metadata.getColumnName(i), Comparable.class));
@@ -148,4 +143,4 @@ public class JDBCKnoxShellTableBuilder extends KnoxShellTableBuilder {
processResultSet(resultSet);
return this.table;
}
-}
+}
\ No newline at end of file
diff --git a/gateway-shell/src/main/java/org/apache/knox/gateway/shell/table/KnoxShellTable.java b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/table/KnoxShellTable.java
index 591f8aa..daaea31 100644
--- a/gateway-shell/src/main/java/org/apache/knox/gateway/shell/table/KnoxShellTable.java
+++ b/gateway-shell/src/main/java/org/apache/knox/gateway/shell/table/KnoxShellTable.java
@@ -55,7 +55,7 @@ public class KnoxShellTable {
String title;
long id;
- KnoxShellTable() {
+ public KnoxShellTable() {
this.id = getUniqueTableId();
}
diff --git a/gateway-shell/src/test/java/org/apache/knox/gateway/shell/table/KnoxShellTableTest.java b/gateway-shell/src/test/java/org/apache/knox/gateway/shell/table/KnoxShellTableTest.java
index 470cf4f..3d8c571 100644
--- a/gateway-shell/src/test/java/org/apache/knox/gateway/shell/table/KnoxShellTableTest.java
+++ b/gateway-shell/src/test/java/org/apache/knox/gateway/shell/table/KnoxShellTableTest.java
@@ -412,7 +412,7 @@ public class KnoxShellTableTest {
return table;
}
};
- builder.username("joe").pwd("pass").sql("select * from book");
+ builder.username("joe").password("pass").sql("select * from book");
}
@Test