You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hive.apache.org by ai...@apache.org on 2016/10/17 17:08:49 UTC
hive git commit: HIVE-14063: beeline to auto connect to the HiveServer2 (Vihang Karajgaonkar, reviewed by Aihua Xu, Szehon Ho, Sergio Peña)
Repository: hive
Updated Branches:
refs/heads/master 9caf23001 -> 8029e11b3
HIVE-14063: beeline to auto connect to the HiveServer2 (Vihang Karajgaonkar, reviewed by Aihua Xu, Szehon Ho, Sergio Pe�a)
Project: http://git-wip-us.apache.org/repos/asf/hive/repo
Commit: http://git-wip-us.apache.org/repos/asf/hive/commit/8029e11b
Tree: http://git-wip-us.apache.org/repos/asf/hive/tree/8029e11b
Diff: http://git-wip-us.apache.org/repos/asf/hive/diff/8029e11b
Branch: refs/heads/master
Commit: 8029e11b3c913e0aebc0a719a19b85d96db28a32
Parents: 9caf230
Author: Aihua Xu <ai...@apache.org>
Authored: Mon Oct 17 13:06:30 2016 -0400
Committer: Aihua Xu <ai...@apache.org>
Committed: Mon Oct 17 13:08:29 2016 -0400
----------------------------------------------------------------------
.../java/org/apache/hive/beeline/BeeLine.java | 176 ++++++++++-----
.../java/org/apache/hive/beeline/Commands.java | 52 +++--
.../BeelineHS2ConnectionFileParseException.java | 30 +++
.../hs2connection/HS2ConnectionFileParser.java | 88 ++++++++
.../hs2connection/HS2ConnectionFileUtils.java | 119 +++++++++++
.../HiveSiteHS2ConnectionFileParser.java | 172 +++++++++++++++
.../UserHS2ConnectionFileParser.java | 117 ++++++++++
.../apache/hive/beeline/TestBeeLineHistory.java | 4 +-
.../TestUserHS2ConnectionFileParser.java | 211 ++++++++++++++++++
beeline/src/test/resources/hive-site.xml | 5 +
.../test-hs2-conn-conf-kerberos-http.xml | 48 +++++
.../test-hs2-conn-conf-kerberos-nossl.xml | 32 +++
.../test-hs2-conn-conf-kerberos-ssl.xml | 40 ++++
.../resources/test-hs2-connection-conf-list.xml | 36 ++++
.../test-hs2-connection-config-noauth.xml | 28 +++
.../test-hs2-connection-multi-conf-list.xml | 37 ++++
.../test-hs2-connection-zookeeper-config.xml | 32 +++
.../TestBeelineConnectionUsingHiveSite.java | 109 ++++++++++
.../TestBeelineWithHS2ConnectionFile.java | 214 +++++++++++++++++++
.../TestBeelineWithUserHs2ConnectionFile.java | 129 +++++++++++
20 files changed, 1612 insertions(+), 67 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/hive/blob/8029e11b/beeline/src/java/org/apache/hive/beeline/BeeLine.java
----------------------------------------------------------------------
diff --git a/beeline/src/java/org/apache/hive/beeline/BeeLine.java b/beeline/src/java/org/apache/hive/beeline/BeeLine.java
index 79922d2..fdbe0a2 100644
--- a/beeline/src/java/org/apache/hive/beeline/BeeLine.java
+++ b/beeline/src/java/org/apache/hive/beeline/BeeLine.java
@@ -28,6 +28,7 @@ import java.io.Closeable;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
@@ -93,8 +94,15 @@ import org.apache.hadoop.hive.conf.HiveConf;
import org.apache.hadoop.io.IOUtils;
import org.apache.hive.beeline.cli.CliOptionsProcessor;
import org.apache.hive.common.util.ShutdownHookManager;
+import org.apache.hive.beeline.hs2connection.BeelineHS2ConnectionFileParseException;
+import org.apache.hive.beeline.hs2connection.HS2ConnectionFileUtils;
+import org.apache.hive.beeline.hs2connection.UserHS2ConnectionFileParser;
+import org.apache.hive.beeline.hs2connection.HS2ConnectionFileParser;
+import org.apache.hive.beeline.hs2connection.HiveSiteHS2ConnectionFileParser;
import org.apache.thrift.transport.TTransportException;
+import com.google.common.annotations.VisibleForTesting;
+
import org.apache.hive.jdbc.Utils;
import org.apache.hive.jdbc.Utils.JdbcConnectionParams;
@@ -279,7 +287,6 @@ public class BeeLine implements Closeable {
"org.apache.hadoop.hive.jdbc.HiveDriver",
}));
-
static {
try {
Class.forName("jline.console.ConsoleReader");
@@ -728,6 +735,46 @@ public class BeeLine implements Closeable {
return -1;
}
+ boolean connSuccessful = connectUsingArgs(cl);
+ // checks if default hs2 connection configuration file is present
+ // and uses it to connect if found
+ // no-op if the file is not present
+ if(!connSuccessful && !exit) {
+ connSuccessful = defaultBeelineConnect();
+ }
+
+ int code = 0;
+ if (cl.getOptionValues('e') != null) {
+ commands = Arrays.asList(cl.getOptionValues('e'));
+ }
+
+ if (!commands.isEmpty() && getOpts().getScriptFile() != null) {
+ error("The '-e' and '-f' options cannot be specified simultaneously");
+ return 1;
+ } else if(!commands.isEmpty() && !connSuccessful) {
+ error("Cannot run commands specified using -e. No current connection");
+ return 1;
+ }
+ if (!commands.isEmpty()) {
+ for (Iterator<String> i = commands.iterator(); i.hasNext();) {
+ String command = i.next().toString();
+ debug(loc("executing-command", command));
+ if (!dispatch(command)) {
+ code++;
+ }
+ }
+ exit = true; // execute and exit
+ }
+ return code;
+ }
+
+
+ /*
+ * Connects using the command line arguments. There are two
+ * possible ways to connect here 1. using the cmd line arguments like -u
+ * or using !properties <property-file>
+ */
+ private boolean connectUsingArgs(CommandLine cl) {
String driver = null, user = null, pass = null, url = null;
String auth = null;
@@ -735,7 +782,7 @@ public class BeeLine implements Closeable {
if (cl.hasOption("help")) {
usage();
getOpts().setHelpAsked(true);
- return 0;
+ return true;
}
Properties hiveVars = cl.getOptionProperties("hivevar");
@@ -764,24 +811,7 @@ public class BeeLine implements Closeable {
}
getOpts().setInitFiles(cl.getOptionValues("i"));
getOpts().setScriptFile(cl.getOptionValue("f"));
- if (cl.getOptionValues('e') != null) {
- commands = Arrays.asList(cl.getOptionValues('e'));
- }
-
- if (!commands.isEmpty() && getOpts().getScriptFile() != null) {
- System.err.println("The '-e' and '-f' options cannot be specified simultaneously");
- return 1;
- }
- // TODO: temporary disable this for easier debugging
- /*
- if (url == null) {
- url = BEELINE_DEFAULT_JDBC_URL;
- }
- if (driver == null) {
- driver = BEELINE_DEFAULT_JDBC_DRIVER;
- }
- */
if (url != null) {
if (user == null) {
@@ -795,38 +825,25 @@ public class BeeLine implements Closeable {
String com = constructCmd(url, user, pass, driver, false);
String comForDebug = constructCmd(url, user, pass, driver, true);
debug("issuing: " + comForDebug);
- dispatch(com);
- }
-
- // load property file
- String propertyFile = cl.getOptionValue("property-file");
- if (propertyFile != null) {
- try {
- this.consoleReader = new ConsoleReader();
- } catch (IOException e) {
- handleException(e);
- }
- if (!dispatch("!properties " + propertyFile)) {
- exit = true;
- return 1;
- }
- }
-
- int code = 0;
- if (!commands.isEmpty()) {
- for (Iterator<String> i = commands.iterator(); i.hasNext();) {
- String command = i.next().toString();
- debug(loc("executing-command", command));
- if (!dispatch(command)) {
- code++;
+ return dispatch(com);
+ } else {
+ // load property file
+ String propertyFile = cl.getOptionValue("property-file");
+ if (propertyFile != null) {
+ try {
+ this.consoleReader = new ConsoleReader();
+ } catch (IOException e) {
+ handleException(e);
+ }
+ if (!dispatch("!properties " + propertyFile)) {
+ exit = true;
+ return false;
}
}
- exit = true; // execute and exit
}
- return code;
+ return false;
}
-
private void setHiveConfVar(String key, String val) {
getOpts().getHiveConfVariables().put(key, val);
if (HiveConf.ConfVars.HIVE_EXECUTION_ENGINE.varname.equals(key) && "mr".equals(val)) {
@@ -906,13 +923,74 @@ public class BeeLine implements Closeable {
} catch (Exception e) {
// ignore
}
- ConsoleReader reader = getConsoleReader(inputStream);
+ ConsoleReader reader = initializeConsoleReader(inputStream);
return execute(reader, false);
} finally {
close();
}
}
+ /*
+ * Attempts to make a connection using default HS2 connection config file if available
+ * if there connection is not made return false
+ *
+ */
+ private boolean defaultBeelineConnect() {
+ String url;
+ try {
+ initializeConsoleReader(null);
+ url = getDefaultConnectionUrl();
+ if (url == null) {
+ debug("Default hs2 connection config file not found");
+ return false;
+ }
+ } catch (BeelineHS2ConnectionFileParseException | IOException e) {
+ error(e);
+ return false;
+ }
+ return dispatch("!connect " + url);
+ }
+
+
+ private String getDefaultConnectionUrl() throws BeelineHS2ConnectionFileParseException {
+ HS2ConnectionFileParser userHS2ConnFileParser = getUserHS2ConnFileParser();
+ if (!userHS2ConnFileParser.configExists()) {
+ // nothing to do if there is no user HS2 connection configuration file
+ return null;
+ }
+ // get the connection properties from user specific config file
+ Properties userConnectionProperties = userHS2ConnFileParser.getConnectionProperties();
+ // load the HS2 connection url properties from hive-site.xml if it is present in the classpath
+ HS2ConnectionFileParser hiveSiteParser = getHiveSiteHS2ConnectionFileParser();
+ Properties hiveSiteConnectionProperties = hiveSiteParser.getConnectionProperties();
+ // add/override properties found from hive-site with user-specific properties
+ for (String key : userConnectionProperties.stringPropertyNames()) {
+ if (hiveSiteConnectionProperties.containsKey(key)) {
+ debug("Overriding connection url property " + key
+ + " from user connection configuration file");
+ }
+ hiveSiteConnectionProperties.setProperty(key, userConnectionProperties.getProperty(key));
+ }
+ // return the url based on the aggregated connection properties
+ return HS2ConnectionFileUtils.getUrl(hiveSiteConnectionProperties);
+ }
+
+ /*
+ * Increased visibility of this method is only for providing better test coverage
+ */
+ @VisibleForTesting
+ public HS2ConnectionFileParser getUserHS2ConnFileParser() {
+ return new UserHS2ConnectionFileParser();
+ }
+
+ /*
+ * Increased visibility of this method is only for providing better test coverage
+ */
+ @VisibleForTesting
+ public HS2ConnectionFileParser getHiveSiteHS2ConnectionFileParser() {
+ return new HiveSiteHS2ConnectionFileParser();
+ }
+
int runInit() {
String initFiles[] = getOpts().getInitFiles();
if (initFiles != null && initFiles.length != 0) {
@@ -972,7 +1050,7 @@ public class BeeLine implements Closeable {
} else {
initStream = new FileInputStream(fileName);
}
- return execute(getConsoleReader(initStream), !getOpts().getForce());
+ return execute(initializeConsoleReader(initStream), !getOpts().getForce());
} catch (Throwable t) {
handleException(t);
return ERRNO_OTHER;
@@ -1017,7 +1095,7 @@ public class BeeLine implements Closeable {
commands.closeall(null);
}
- public ConsoleReader getConsoleReader(InputStream inputStream) throws IOException {
+ public ConsoleReader initializeConsoleReader(InputStream inputStream) throws IOException {
if (inputStream != null) {
// ### NOTE: fix for sf.net bug 879425.
// Working around an issue in jline-2.1.2, see https://github.com/jline/jline/issues/10
http://git-wip-us.apache.org/repos/asf/hive/blob/8029e11b/beeline/src/java/org/apache/hive/beeline/Commands.java
----------------------------------------------------------------------
diff --git a/beeline/src/java/org/apache/hive/beeline/Commands.java b/beeline/src/java/org/apache/hive/beeline/Commands.java
index 039e354..6c3e7f7 100644
--- a/beeline/src/java/org/apache/hive/beeline/Commands.java
+++ b/beeline/src/java/org/apache/hive/beeline/Commands.java
@@ -22,12 +22,6 @@
*/
package org.apache.hive.beeline;
-import org.apache.hadoop.hive.conf.HiveConf;
-import org.apache.hadoop.hive.conf.HiveVariableSource;
-import org.apache.hadoop.hive.conf.SystemVariables;
-import org.apache.hadoop.hive.conf.VariableSubstitution;
-import org.apache.hadoop.io.IOUtils;
-
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
@@ -46,8 +40,8 @@ import java.sql.DatabaseMetaData;
import java.sql.Driver;
import java.sql.ResultSet;
import java.sql.SQLException;
-import java.sql.Statement;
import java.sql.SQLWarning;
+import java.sql.Statement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@@ -60,6 +54,12 @@ import java.util.Set;
import java.util.TreeSet;
import org.apache.hadoop.hive.common.cli.ShellCmdExecutor;
+import org.apache.hadoop.hive.conf.HiveConf;
+import org.apache.hadoop.hive.conf.HiveConf.ConfVars;
+import org.apache.hadoop.hive.conf.HiveVariableSource;
+import org.apache.hadoop.hive.conf.SystemVariables;
+import org.apache.hadoop.hive.conf.VariableSubstitution;
+import org.apache.hadoop.io.IOUtils;
import org.apache.hive.jdbc.HiveStatement;
import org.apache.hive.jdbc.Utils;
import org.apache.hive.jdbc.Utils.JdbcConnectionParams;
@@ -1037,9 +1037,7 @@ public class Commands {
}
public String handleMultiLineCmd(String line) throws IOException {
- //When using -e, console reader is not initialized and command is a single line
- while (beeLine.getConsoleReader() != null && !(line.trim().endsWith(";")) && beeLine.getOpts()
- .isAllowMultiLineCommand()) {
+ while (isMultiLine(line) && beeLine.getOpts().isAllowMultiLineCommand()) {
StringBuilder prompt = new StringBuilder(beeLine.getPrompt());
if (!beeLine.getOpts().isSilent()) {
@@ -1049,7 +1047,6 @@ public class Commands {
}
}
}
-
String extra;
if (beeLine.getOpts().isSilent() && beeLine.getOpts().getScriptFile() != null) {
extra = beeLine.getConsoleReader().readLine(null, jline.console.ConsoleReader.NULL_MASK);
@@ -1067,6 +1064,26 @@ public class Commands {
return line;
}
+ //returns true if statement represented by line is
+ //not complete and needs additional reading from
+ //console. Used in handleMultiLineCmd method
+ //assumes line would never be null when this method is called
+ private boolean isMultiLine(String line) {
+ line = line.trim();
+ if (line.endsWith(";")) {
+ return false;
+ }
+ if (beeLine.isComment(line)) {
+ return false;
+ }
+ // handles the case like line = show tables; --test comment
+ List<String> cmds = getCmdList(line, false);
+ if(!cmds.isEmpty() && cmds.get(cmds.size()-1).trim().startsWith("--")) {
+ return false;
+ }
+ return true;
+ }
+
public boolean sql(String line, boolean entireLineAsCommand) {
return execute(line, false, entireLineAsCommand);
}
@@ -1409,6 +1426,10 @@ public class Commands {
value = Utils.parsePropertyFromUrl(url, JdbcConnectionParams.AUTH_PASSWD);
if (value != null) {
props.setProperty(JdbcConnectionParams.AUTH_PASSWD, value);
+ } else {
+ //if the password is not provided, beeline assumes a empty string as
+ //password
+ props.setProperty(JdbcConnectionParams.AUTH_PASSWD, "");
}
}
@@ -1465,7 +1486,6 @@ public class Commands {
return null;
}
-
public boolean connect(Properties props) throws IOException {
String url = getProperty(props, new String[] {
JdbcConnectionParams.PROPERTY_URL,
@@ -1507,13 +1527,14 @@ public class Commands {
beeLine.info("Connecting to " + url);
if (Utils.parsePropertyFromUrl(url, JdbcConnectionParams.AUTH_PRINCIPAL) == null) {
+ String urlForPrompt = url.substring(0, url.contains(";") ? url.indexOf(';') : url.length());
if (username == null) {
- username = beeLine.getConsoleReader().readLine("Enter username for " + url + ": ");
+ username = beeLine.getConsoleReader().readLine("Enter username for " + urlForPrompt + ": ");
}
props.setProperty(JdbcConnectionParams.AUTH_USER, username);
if (password == null) {
- password = beeLine.getConsoleReader().readLine("Enter password for " + url + ": ",
- new Character('*'));
+ password = beeLine.getConsoleReader().readLine("Enter password for " + urlForPrompt + ": ",
+ new Character('*'));
}
props.setProperty(JdbcConnectionParams.AUTH_PASSWD, password);
}
@@ -1539,7 +1560,6 @@ public class Commands {
}
}
-
public boolean rehash(String line) {
try {
if (!(beeLine.assertConnection())) {
http://git-wip-us.apache.org/repos/asf/hive/blob/8029e11b/beeline/src/java/org/apache/hive/beeline/hs2connection/BeelineHS2ConnectionFileParseException.java
----------------------------------------------------------------------
diff --git a/beeline/src/java/org/apache/hive/beeline/hs2connection/BeelineHS2ConnectionFileParseException.java b/beeline/src/java/org/apache/hive/beeline/hs2connection/BeelineHS2ConnectionFileParseException.java
new file mode 100644
index 0000000..6e60186
--- /dev/null
+++ b/beeline/src/java/org/apache/hive/beeline/hs2connection/BeelineHS2ConnectionFileParseException.java
@@ -0,0 +1,30 @@
+/**
+ * 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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.hive.beeline.hs2connection;
+
+public class BeelineHS2ConnectionFileParseException extends Exception {
+ private static final long serialVersionUID = -748635913718300617L;
+
+ BeelineHS2ConnectionFileParseException(String msg, Exception e) {
+ super(msg, e);
+ }
+
+ public BeelineHS2ConnectionFileParseException(String msg) {
+ super(msg);
+ }
+}
http://git-wip-us.apache.org/repos/asf/hive/blob/8029e11b/beeline/src/java/org/apache/hive/beeline/hs2connection/HS2ConnectionFileParser.java
----------------------------------------------------------------------
diff --git a/beeline/src/java/org/apache/hive/beeline/hs2connection/HS2ConnectionFileParser.java b/beeline/src/java/org/apache/hive/beeline/hs2connection/HS2ConnectionFileParser.java
new file mode 100644
index 0000000..7173ee8
--- /dev/null
+++ b/beeline/src/java/org/apache/hive/beeline/hs2connection/HS2ConnectionFileParser.java
@@ -0,0 +1,88 @@
+/**
+ * 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.hive.beeline.hs2connection;
+
+import java.util.Properties;
+
+/**
+ * HS2ConnectionFileParser provides a interface to be used by Beeline to parse a configuration (file
+ * or otherwise) to return a Java Properties object which contain key value pairs to be used to construct
+ * connection URL automatically for the Beeline connection
+ */
+public interface HS2ConnectionFileParser {
+ /**
+ * prefix string used for the keys
+ */
+ public static final String BEELINE_CONNECTION_PROPERTY_PREFIX = "beeline.hs2.connection.";
+ /**
+ * Property key used to provide the URL prefix for the connection URL
+ */
+ public static final String URL_PREFIX_PROPERTY_KEY = "url_prefix";
+ /**
+ * Property key used to provide the default database in the connection URL
+ */
+ public static final String DEFAULT_DB_PROPERTY_KEY = "defaultDB";
+ /**
+ * Property key used to provide the hosts in the connection URL
+ */
+ public static final String HOST_PROPERTY_KEY = "hosts";
+ /**
+ * Property key used to provide the hive configuration key value pairs in the connection URL
+ */
+ public static final String HIVE_CONF_PROPERTY_KEY = "hiveconf";
+ /**
+ * Property key used to provide the hive variables in the connection URL
+ */
+ public static final String HIVE_VAR_PROPERTY_KEY = "hivevar";
+
+ /**
+ * Returns a Java properties object which contain the key value pairs which can be used in the
+ * Beeline connection URL<p>
+ * The properties returned must include url_prefix and hosts<p>
+ * Following are some examples of the URLs and returned properties object<p>
+ * <ul>
+ * <li> jdbc:hive2://hs2-instance1.example.com:10000/default;user=hive;password=mypassword should
+ * return [ "url_prefix"="jdbc:hive2://", "hosts"="hs2-instance1.example.com:10000",
+ * "defaultDB"=default, "user"="hive", "password"="mypassword" ]
+ * <li>jdbc:hive2://zk-instance1:10001,zk-instance2:10002,zk-instance3:10003/default;
+ * serviceDiscoveryMode=zooKeeper;zooKeeperNamespace=hiveserver2 should return [
+ * "url_prefix"="jdbc:hive2://",
+ * "hosts"="zk-instance1:10001,zk-instance2:10002,zk-instance3:10003", "defaultDB"="default",
+ * "serviceDiscoveryMode"="zooKeeper", "zooKeeperNamespace"="hiveserver2" ]
+ *
+ * <li>If hive_conf_list and hive_var_list is present in the url it should return a comma separated
+ * key=value pairs for each of them<p>
+ * For example :<p>
+ * jdbc:hive2://hs2-instance1.example.com:10000/default;user=hive?hive.cli.print.currentdb=true;
+ * hive.cli.print.header=true#hivevar:mytbl=customers;hivevar:mycol=id it should return [
+ * "url_prefix"="jdbc:hive2://", "hosts"="hs2-instance1.example.com:10000", "defaultDB"="default",
+ * "user"="hive", "hiveconf"="hive.cli.print.currentdb=true, hive.cli.print.header=true",
+ * "hivevar"="hivevar:mytb1=customers, hivevar:mycol=id" ]
+ * </ul>
+ *
+ * @return Properties object which contain connection URL properties for Beeline connection. Returns an empty properties
+ * object if the connection configuration is not found
+ * @throws BeelineHS2ConnectionFileParseException if there is invalid key with appropriate message
+ */
+ Properties getConnectionProperties() throws BeelineHS2ConnectionFileParseException;
+ /**
+ *
+ * @return returns true if the configuration exists else returns false
+ */
+ boolean configExists();
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/hive/blob/8029e11b/beeline/src/java/org/apache/hive/beeline/hs2connection/HS2ConnectionFileUtils.java
----------------------------------------------------------------------
diff --git a/beeline/src/java/org/apache/hive/beeline/hs2connection/HS2ConnectionFileUtils.java b/beeline/src/java/org/apache/hive/beeline/hs2connection/HS2ConnectionFileUtils.java
new file mode 100644
index 0000000..ae9c4df
--- /dev/null
+++ b/beeline/src/java/org/apache/hive/beeline/hs2connection/HS2ConnectionFileUtils.java
@@ -0,0 +1,119 @@
+/**
+ * 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.hive.beeline.hs2connection;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Properties;
+
+public class HS2ConnectionFileUtils {
+
+ public static String getUrl(Properties props) throws BeelineHS2ConnectionFileParseException {
+ if (props == null || props.isEmpty()) {
+ return null;
+ }
+ // use remove instead of get so that it is not parsed again
+ // in the for loop below
+ String urlPrefix = (String) props.remove(HS2ConnectionFileParser.URL_PREFIX_PROPERTY_KEY);
+ if (urlPrefix == null || urlPrefix.isEmpty()) {
+ throw new BeelineHS2ConnectionFileParseException("url_prefix parameter cannot be empty");
+ }
+
+ String hosts = (String) props.remove(HS2ConnectionFileParser.HOST_PROPERTY_KEY);
+ if (hosts == null || hosts.isEmpty()) {
+ throw new BeelineHS2ConnectionFileParseException("hosts parameter cannot be empty");
+ }
+ String defaultDB = (String) props.remove(HS2ConnectionFileParser.DEFAULT_DB_PROPERTY_KEY);
+ if (defaultDB == null) {
+ defaultDB = "default";
+ }
+ // collect the hiveConfList and HiveVarList separately so that they can be
+ // appended once all the session list are added to the url
+ String hiveConfProperties = "";
+ if (props.containsKey(HS2ConnectionFileParser.HIVE_CONF_PROPERTY_KEY)) {
+ hiveConfProperties = extractHiveVariables(
+ (String) props.remove(HS2ConnectionFileParser.HIVE_CONF_PROPERTY_KEY), true);
+ }
+
+ String hiveVarProperties = "";
+ if (props.containsKey(HS2ConnectionFileParser.HIVE_VAR_PROPERTY_KEY)) {
+ hiveVarProperties = extractHiveVariables(
+ (String) props.remove(HS2ConnectionFileParser.HIVE_VAR_PROPERTY_KEY), false);
+ }
+ StringBuilder urlSb = new StringBuilder();
+ urlSb.append(urlPrefix.trim());
+ urlSb.append(hosts.trim());
+ urlSb.append(File.separator);
+ urlSb.append(defaultDB.trim());
+ List<String> keys = new ArrayList<>(props.stringPropertyNames());
+ // sorting the keys from the properties helps to create
+ // a deterministic url which is tested for various configuration in
+ // TestHS2ConnectionConfigFileManager
+ Collections.sort(keys);
+ for (String propertyName : keys) {
+ urlSb.append(";");
+ urlSb.append(propertyName);
+ urlSb.append("=");
+ urlSb.append(props.getProperty(propertyName));
+ }
+ if (!hiveConfProperties.isEmpty()) {
+ urlSb.append(hiveConfProperties.toString());
+ }
+ if (!hiveVarProperties.isEmpty()) {
+ urlSb.append(hiveVarProperties.toString());
+ }
+ return urlSb.toString();
+ }
+
+ private static String extractHiveVariables(String propertyValue, boolean isHiveConf)
+ throws BeelineHS2ConnectionFileParseException {
+ StringBuilder hivePropertiesList = new StringBuilder();
+ String delimiter;
+ if (isHiveConf) {
+ delimiter = "?";
+ } else {
+ delimiter = "#";
+ }
+ hivePropertiesList.append(delimiter);
+ addPropertyValues(propertyValue, hivePropertiesList);
+ return hivePropertiesList.toString();
+ }
+
+ private static void addPropertyValues(String value, StringBuilder hivePropertiesList)
+ throws BeelineHS2ConnectionFileParseException {
+ // There could be multiple keyValuePairs separated by comma
+ String[] values = value.split(",");
+ boolean first = true;
+ for (String keyValuePair : values) {
+ String[] keyValue = keyValuePair.split("=");
+ if (keyValue.length != 2) {
+ throw new BeelineHS2ConnectionFileParseException("Unable to parse " + keyValuePair
+ + " in hs2 connection config file");
+ }
+ if (!first) {
+ hivePropertiesList.append(";");
+ }
+ first = false;
+ hivePropertiesList.append(keyValue[0].trim());
+ hivePropertiesList.append("=");
+ hivePropertiesList.append(keyValue[1].trim());
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/hive/blob/8029e11b/beeline/src/java/org/apache/hive/beeline/hs2connection/HiveSiteHS2ConnectionFileParser.java
----------------------------------------------------------------------
diff --git a/beeline/src/java/org/apache/hive/beeline/hs2connection/HiveSiteHS2ConnectionFileParser.java b/beeline/src/java/org/apache/hive/beeline/hs2connection/HiveSiteHS2ConnectionFileParser.java
new file mode 100644
index 0000000..f1814fa
--- /dev/null
+++ b/beeline/src/java/org/apache/hive/beeline/hs2connection/HiveSiteHS2ConnectionFileParser.java
@@ -0,0 +1,172 @@
+/**
+ * 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.hive.beeline.hs2connection;
+
+import java.net.InetAddress;
+import java.net.URL;
+import java.net.UnknownHostException;
+import java.util.Properties;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hive.common.ServerUtils;
+import org.apache.hadoop.hive.conf.HiveConf;
+import org.apache.hadoop.hive.conf.HiveConf.ConfVars;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.annotations.VisibleForTesting;
+
+/*
+ * Looks for a hive-site.xml from the classpath. If found this class parses the hive-site.xml
+ * to return a set of connection properties which can be used to construct the connection url
+ * for Beeline connection
+ */
+public class HiveSiteHS2ConnectionFileParser implements HS2ConnectionFileParser {
+ private Configuration conf;
+ private final URL hiveSiteURI;
+ private final static String TRUSTSTORE_PASS_PROP = "javax.net.ssl.trustStorePassword";
+ private final static String TRUSTSTORE_PROP = "javax.net.ssl.trustStore";
+ private static final Logger log = LoggerFactory.getLogger(HiveSiteHS2ConnectionFileParser.class);
+
+ public HiveSiteHS2ConnectionFileParser() {
+ hiveSiteURI = HiveConf.getHiveSiteLocation();
+ conf = new Configuration();
+ if(hiveSiteURI == null) {
+ log.debug("hive-site.xml not found for constructing the connection URL");
+ } else {
+ log.info("Using hive-site.xml at " + hiveSiteURI);
+ conf.addResource(hiveSiteURI);
+ }
+ }
+
+ @VisibleForTesting
+ void setHiveConf(HiveConf hiveConf) {
+ this.conf = hiveConf;
+ }
+
+ @Override
+ public Properties getConnectionProperties() throws BeelineHS2ConnectionFileParseException {
+ Properties props = new Properties();
+ if(!configExists()) {
+ return props;
+ }
+ props.setProperty(HS2ConnectionFileParser.URL_PREFIX_PROPERTY_KEY, "jdbc:hive2://");
+ addHosts(props);
+ addSSL(props);
+ addKerberos(props);
+ addHttp(props);
+ return props;
+ }
+
+ private void addSSL(Properties props) {
+ if (!HiveConf.getBoolVar(conf, HiveConf.ConfVars.HIVE_SERVER2_USE_SSL)) {
+ return;
+ } else {
+ props.setProperty("ssl", "true");
+ }
+ String truststore = System.getenv(TRUSTSTORE_PROP);
+ if (truststore != null && truststore.isEmpty()) {
+ props.setProperty("sslTruststore", truststore);
+ }
+ String trustStorePassword = System.getenv(TRUSTSTORE_PASS_PROP);
+ if (trustStorePassword != null && !trustStorePassword.isEmpty()) {
+ props.setProperty("trustStorePassword", trustStorePassword);
+ }
+ String saslQop = HiveConf.getVar(conf, ConfVars.HIVE_SERVER2_THRIFT_SASL_QOP);
+ if (!"auth".equalsIgnoreCase(saslQop)) {
+ props.setProperty("sasl.qop", saslQop);
+ }
+ }
+
+ private void addKerberos(Properties props) {
+ if ("KERBEROS".equals(HiveConf.getVar(conf, HiveConf.ConfVars.HIVE_SERVER2_AUTHENTICATION))) {
+ props.setProperty("principal",
+ HiveConf.getVar(conf, HiveConf.ConfVars.HIVE_SERVER2_KERBEROS_PRINCIPAL));
+ }
+ }
+
+ private void addHttp(Properties props) {
+ if ("http".equalsIgnoreCase(HiveConf.getVar(conf, ConfVars.HIVE_SERVER2_TRANSPORT_MODE))) {
+ props.setProperty("transportMode", "http");
+ } else {
+ return;
+ }
+ props.setProperty("httpPath", HiveConf.getVar(conf, ConfVars.HIVE_SERVER2_THRIFT_HTTP_PATH));
+ }
+
+ private void addHosts(Properties props) throws BeelineHS2ConnectionFileParseException {
+ // if zk HA is enabled get hosts property
+ if (HiveConf.getBoolVar(conf,
+ HiveConf.ConfVars.HIVE_SERVER2_SUPPORT_DYNAMIC_SERVICE_DISCOVERY)) {
+ addZKServiceDiscoveryHosts(props);
+ } else {
+ addDefaultHS2Hosts(props);
+ }
+ }
+
+ private void addZKServiceDiscoveryHosts(Properties props)
+ throws BeelineHS2ConnectionFileParseException {
+ props.setProperty("serviceDiscoveryMode", "zooKeeper");
+ props.setProperty("zooKeeperNamespace",
+ HiveConf.getVar(conf, ConfVars.HIVE_SERVER2_ZOOKEEPER_NAMESPACE));
+ props.setProperty("hosts", HiveConf.getVar(conf, ConfVars.HIVE_ZOOKEEPER_QUORUM));
+ }
+
+ private void addDefaultHS2Hosts(Properties props) throws BeelineHS2ConnectionFileParseException {
+ String hiveHost = System.getenv("HIVE_SERVER2_THRIFT_BIND_HOST");
+ if (hiveHost == null) {
+ hiveHost = HiveConf.getVar(conf, HiveConf.ConfVars.HIVE_SERVER2_THRIFT_BIND_HOST);
+ }
+
+ InetAddress serverIPAddress;
+ try {
+ serverIPAddress = ServerUtils.getHostAddress(hiveHost);
+ } catch (UnknownHostException e) {
+ throw new BeelineHS2ConnectionFileParseException(e.getMessage(), e);
+ }
+ int portNum = getPortNum(
+ "http".equalsIgnoreCase(HiveConf.getVar(conf, ConfVars.HIVE_SERVER2_TRANSPORT_MODE)));
+ props.setProperty("hosts", serverIPAddress.getHostName() + ":" + portNum);
+ }
+
+ private int getPortNum(boolean isHttp) {
+ String portString;
+ int portNum;
+ if (isHttp) {
+ portString = System.getenv("HIVE_SERVER2_THRIFT_HTTP_PORT");
+ if (portString != null) {
+ portNum = Integer.parseInt(portString);
+ } else {
+ portNum = HiveConf.getIntVar(conf, ConfVars.HIVE_SERVER2_THRIFT_HTTP_PORT);
+ }
+ } else {
+ portString = System.getenv("HIVE_SERVER2_THRIFT_PORT");
+ if (portString != null) {
+ portNum = Integer.parseInt(portString);
+ } else {
+ portNum = HiveConf.getIntVar(conf, ConfVars.HIVE_SERVER2_THRIFT_PORT);
+ }
+ }
+ return portNum;
+ }
+
+ @Override
+ public boolean configExists() {
+ return (hiveSiteURI != null);
+ }
+}
http://git-wip-us.apache.org/repos/asf/hive/blob/8029e11b/beeline/src/java/org/apache/hive/beeline/hs2connection/UserHS2ConnectionFileParser.java
----------------------------------------------------------------------
diff --git a/beeline/src/java/org/apache/hive/beeline/hs2connection/UserHS2ConnectionFileParser.java b/beeline/src/java/org/apache/hive/beeline/hs2connection/UserHS2ConnectionFileParser.java
new file mode 100644
index 0000000..93a6231
--- /dev/null
+++ b/beeline/src/java/org/apache/hive/beeline/hs2connection/UserHS2ConnectionFileParser.java
@@ -0,0 +1,117 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hive.beeline.hs2connection;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.Properties;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.Path;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.annotations.VisibleForTesting;
+
+/**
+ * This class implements HS2ConnectionFileParser for the user-specific connection configuration
+ * file named beeline-hs2-connection.xml. The class looks for this file in
+ * ${user.home}/.beeline, ${HIVE_CONF_DIR} or /etc/conf/hive in that order and uses the first file
+ * found in the above locations.
+ */
+public class UserHS2ConnectionFileParser implements HS2ConnectionFileParser {
+
+ public static final String DEFAULT_CONNECTION_CONFIG_FILE_NAME = "beeline-hs2-connection.xml";
+ public static final String DEFAULT_BEELINE_USER_CONF_LOCATION =
+ System.getProperty("user.home") + File.separator
+ + (System.getProperty("os.name").toLowerCase().indexOf("windows") != -1 ? "" : ".")
+ + "beeline" + File.separator;
+ public static final String ETC_HIVE_CONF_LOCATION =
+ File.separator + "etc" + File.separator + "conf" + File.separator + "hive";
+
+ private final List<String> locations = new ArrayList<>();
+ private static final Logger log = LoggerFactory.getLogger(UserHS2ConnectionFileParser.class);
+
+ public UserHS2ConnectionFileParser() {
+ // file locations to be searched in the correct order
+ locations.add(DEFAULT_BEELINE_USER_CONF_LOCATION + DEFAULT_CONNECTION_CONFIG_FILE_NAME);
+ if (System.getenv("HIVE_CONF_DIR") != null) {
+ locations.add(
+ System.getenv("HIVE_CONF_DIR") + File.separator + DEFAULT_CONNECTION_CONFIG_FILE_NAME);
+ }
+ locations.add(ETC_HIVE_CONF_LOCATION + DEFAULT_CONNECTION_CONFIG_FILE_NAME);
+ }
+
+ @VisibleForTesting
+ UserHS2ConnectionFileParser(List<String> testLocations) {
+ if(testLocations == null) {
+ return;
+ }
+ locations.addAll(testLocations);
+ }
+
+ @Override
+ public Properties getConnectionProperties() throws BeelineHS2ConnectionFileParseException {
+ Properties props = new Properties();
+ String fileLocation = getFileLocation();
+ if (fileLocation == null) {
+ log.debug("User connection configuration file not found");
+ return props;
+ }
+ log.info("Using connection configuration file at " + fileLocation);
+ props.setProperty(HS2ConnectionFileParser.URL_PREFIX_PROPERTY_KEY, "jdbc:hive2://");
+ // load the properties from config file
+ Configuration conf = new Configuration(false);
+ conf.addResource(new Path(new File(fileLocation).toURI()));
+ try {
+ for (Entry<String, String> kv : conf) {
+ String key = kv.getKey();
+ if (key.startsWith(BEELINE_CONNECTION_PROPERTY_PREFIX)) {
+ props.setProperty(key.substring(BEELINE_CONNECTION_PROPERTY_PREFIX.length()),
+ kv.getValue());
+ } else {
+ log.warn("Ignoring " + key + " since it does not start with "
+ + BEELINE_CONNECTION_PROPERTY_PREFIX);
+ }
+ }
+ } catch (Exception ex) {
+ throw new BeelineHS2ConnectionFileParseException(ex.getMessage(), ex);
+ }
+
+ return props;
+ }
+
+ @Override
+ public boolean configExists() {
+ return (getFileLocation() != null);
+ }
+ /*
+ * This method looks in locations specified above and returns the first location where the file
+ * exists. If the file does not exist in any one of the locations it returns null
+ */
+ String getFileLocation() {
+ for (String location : locations) {
+ if (new File(location).exists()) {
+ return location;
+ }
+ }
+ return null;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/hive/blob/8029e11b/beeline/src/test/org/apache/hive/beeline/TestBeeLineHistory.java
----------------------------------------------------------------------
diff --git a/beeline/src/test/org/apache/hive/beeline/TestBeeLineHistory.java b/beeline/src/test/org/apache/hive/beeline/TestBeeLineHistory.java
index e861976..489db56 100644
--- a/beeline/src/test/org/apache/hive/beeline/TestBeeLineHistory.java
+++ b/beeline/src/test/org/apache/hive/beeline/TestBeeLineHistory.java
@@ -58,7 +58,7 @@ public class TestBeeLineHistory {
BeeLine beeline = new BeeLine();
beeline.getOpts().setHistoryFile(fileName);
beeline.setOutputStream(ops);
- beeline.getConsoleReader(null);
+ beeline.initializeConsoleReader(null);
beeline.dispatch("!history");
String output = os.toString("UTF-8");
int numHistories = output.split("\n").length;
@@ -73,7 +73,7 @@ public class TestBeeLineHistory {
BeeLine beeline = new BeeLine();
beeline.getOpts().setHistoryFile(fileName);
beeline.setOutputStream(ops);
- beeline.getConsoleReader(null);
+ beeline.initializeConsoleReader(null);
beeline.dispatch("!history");
String output = os.toString("UTF-8");
String[] tmp = output.split("\n");
http://git-wip-us.apache.org/repos/asf/hive/blob/8029e11b/beeline/src/test/org/apache/hive/beeline/hs2connection/TestUserHS2ConnectionFileParser.java
----------------------------------------------------------------------
diff --git a/beeline/src/test/org/apache/hive/beeline/hs2connection/TestUserHS2ConnectionFileParser.java b/beeline/src/test/org/apache/hive/beeline/hs2connection/TestUserHS2ConnectionFileParser.java
new file mode 100644
index 0000000..05b2af4
--- /dev/null
+++ b/beeline/src/test/org/apache/hive/beeline/hs2connection/TestUserHS2ConnectionFileParser.java
@@ -0,0 +1,211 @@
+/**
+ * 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.hive.beeline.hs2connection;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.hive.beeline.hs2connection.BeelineHS2ConnectionFileParseException;
+import org.apache.hive.beeline.hs2connection.UserHS2ConnectionFileParser;
+import org.apache.hive.beeline.hs2connection.HS2ConnectionFileUtils;
+import org.apache.hive.common.util.HiveTestUtils;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestUserHS2ConnectionFileParser {
+ private final String LOCATION_1 = System.getProperty("java.io.tmpdir") + "loc1" + File.separator
+ + UserHS2ConnectionFileParser.DEFAULT_CONNECTION_CONFIG_FILE_NAME;
+
+ private final String LOCATION_2 = System.getProperty("java.io.tmpdir") + "loc2" + File.separator
+ + UserHS2ConnectionFileParser.DEFAULT_CONNECTION_CONFIG_FILE_NAME;
+
+ private final String LOCATION_3 = System.getProperty("java.io.tmpdir") + "loc3" + File.separator
+ + UserHS2ConnectionFileParser.DEFAULT_CONNECTION_CONFIG_FILE_NAME;
+
+ List<String> testLocations = new ArrayList<>();
+
+ @After
+ public void cleanUp() {
+ try {
+ deleteFile(LOCATION_1);
+ deleteFile(LOCATION_2);
+ deleteFile(LOCATION_3);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ testLocations.clear();
+ }
+
+ @Test
+ public void testParseNoAuthentication() throws BeelineHS2ConnectionFileParseException {
+ String url = getParsedUrlFromConfigFile("test-hs2-connection-config-noauth.xml");
+ String expectedUrl = "jdbc:hive2://localhost:10000/default;user=hive";
+ Assert.assertTrue("Expected " + expectedUrl + " got " + url, expectedUrl.equals(url));
+ }
+
+ @Test
+ public void testParseZookeeper() throws BeelineHS2ConnectionFileParseException {
+ String url = getParsedUrlFromConfigFile("test-hs2-connection-zookeeper-config.xml");
+ String expectedUrl =
+ "jdbc:hive2://zk-node-1:10000,zk-node-2:10001,zk-node-3:10004/default;serviceDiscoveryMode=zookeeper;zooKeeperNamespace=hiveserver2";
+ Assert.assertTrue("Expected " + expectedUrl + " got " + url, expectedUrl.equals(url));
+ }
+
+ @Test
+ public void testParseWithKerberosNoSSL() throws BeelineHS2ConnectionFileParseException {
+ String url = getParsedUrlFromConfigFile("test-hs2-conn-conf-kerberos-nossl.xml");
+ String expectedUrl =
+ "jdbc:hive2://localhost:10000/default;principal=hive/dummy-hostname@domain.com;ssl=false";
+ Assert.assertTrue("Expected " + expectedUrl + " got " + url, expectedUrl.equals(url));
+ }
+
+ @Test
+ public void testParseWithKerberosSSL() throws BeelineHS2ConnectionFileParseException {
+ String url = getParsedUrlFromConfigFile("test-hs2-conn-conf-kerberos-ssl.xml");
+ String expectedUrl =
+ "jdbc:hive2://localhost:10000/default;principal=hive/dummy-hostname@domain.com;ssl=true;"
+ + "sslTrustStore=test/truststore;trustStorePassword=testTruststorePassword";
+ Assert.assertTrue("Expected " + expectedUrl + " got " + url, expectedUrl.equals(url));
+ }
+
+ @Test
+ public void testParseWithSSLAndHttpMode() throws BeelineHS2ConnectionFileParseException {
+ String url = getParsedUrlFromConfigFile("test-hs2-conn-conf-kerberos-http.xml");
+ String expectedUrl =
+ "jdbc:hive2://localhost:10000/default;httpPath=testHTTPPath;principal=hive/dummy-hostname@domain.com;"
+ + "ssl=true;sslTrustStore=test/truststore;transportMode=http;trustStorePassword=testTruststorePassword";
+ Assert.assertTrue("Expected " + expectedUrl + " got " + url, expectedUrl.equals(url));
+ }
+
+ @Test
+ public void testUrlWithHiveConfValues() throws Exception {
+ String url = getParsedUrlFromConfigFile("test-hs2-connection-conf-list.xml");
+ String expectedUrl =
+ "jdbc:hive2://localhost:10000/default;user=hive?hive.cli.print.current.db=false#testVarName1=value1";
+ Assert.assertTrue("Expected " + expectedUrl + " got " + url, expectedUrl.equals(url));
+ }
+
+ @Test
+ public void testUrlWithMultipleHiveConfValues() throws Exception {
+ String url = getParsedUrlFromConfigFile("test-hs2-connection-multi-conf-list.xml");
+ String expectedUrl =
+ "jdbc:hive2://localhost:10000/default;user=hive?hive.cli.print.current.db=true;"
+ + "hive.cli.print.header=true#testVarName1=value1;testVarName2=value2";
+ Assert.assertTrue("Expected " + expectedUrl + " got " + url, expectedUrl.equals(url));
+ }
+
+ /*
+ * Tests if null value returned when file is not present in any of the lookup locations
+ */
+ @Test
+ public void testNoLocationFoundCase() throws Exception {
+ testLocations.add(LOCATION_1);
+ testLocations.add(LOCATION_2);
+ testLocations.add(LOCATION_3);
+ UserHS2ConnectionFileParser testHS2ConfigManager =
+ new UserHS2ConnectionFileParser(testLocations);
+ Assert.assertTrue(testHS2ConfigManager.getConnectionProperties().isEmpty());
+ }
+
+ /*
+ * Tests if LOCATION_1 is returned when file is present in the first directory in lookup order
+ */
+ @Test
+ public void testGetLocation1() throws Exception {
+ createNewFile(LOCATION_1);
+ testLocations.add(LOCATION_1);
+ testLocations.add(LOCATION_2);
+ testLocations.add(LOCATION_3);
+ UserHS2ConnectionFileParser testHS2ConfigManager =
+ new UserHS2ConnectionFileParser(testLocations);
+ Assert.assertTrue("File location " + LOCATION_1 + " was not returned",
+ LOCATION_1.equals(testHS2ConfigManager.getFileLocation()));
+ }
+
+ /*
+ * Tests if LOCATION_3 is returned when the first file is found is later in lookup order
+ */
+ @Test
+ public void testGetLocation3() throws Exception {
+ createNewFile(LOCATION_3);
+ testLocations.add(LOCATION_1);
+ testLocations.add(LOCATION_2);
+ testLocations.add(LOCATION_3);
+ UserHS2ConnectionFileParser testHS2ConfigManager =
+ new UserHS2ConnectionFileParser(testLocations);
+ Assert.assertTrue("File location " + LOCATION_3 + " was not returned",
+ LOCATION_3.equals(testHS2ConfigManager.getFileLocation()));
+ }
+
+ /*
+ * Tests if it returns the first file present in the lookup order when files are present in the
+ * lookup order
+ */
+ @Test
+ public void testGetLocationOrder() throws Exception {
+ createNewFile(LOCATION_2);
+ createNewFile(LOCATION_3);
+ testLocations.add(LOCATION_1);
+ testLocations.add(LOCATION_2);
+ testLocations.add(LOCATION_3);
+ UserHS2ConnectionFileParser testHS2ConfigManager =
+ new UserHS2ConnectionFileParser(testLocations);
+ Assert.assertTrue("File location " + LOCATION_2 + " was not returned",
+ LOCATION_2.equals(testHS2ConfigManager.getFileLocation()));
+ }
+
+ private String getParsedUrlFromConfigFile(String filename)
+ throws BeelineHS2ConnectionFileParseException {
+ String path = HiveTestUtils.getFileFromClasspath(filename);
+ testLocations.add(path);
+ UserHS2ConnectionFileParser testHS2ConfigManager =
+ new UserHS2ConnectionFileParser(testLocations);
+
+ String url = HS2ConnectionFileUtils.getUrl(testHS2ConfigManager.getConnectionProperties());
+ return url;
+ }
+
+ private void createNewFile(final String path) throws Exception {
+ File file = new File(path);
+ if (file.exists()) {
+ return;
+ }
+ String dir = path.substring(0,
+ path.indexOf(UserHS2ConnectionFileParser.DEFAULT_CONNECTION_CONFIG_FILE_NAME));
+ if (!new File(dir).exists()) {
+ if (!new File(dir).mkdirs()) {
+ throw new Exception("Could not create directory " + dir);
+ }
+ }
+ if (!file.createNewFile()) {
+ throw new Exception("Could not create new file at " + path);
+ }
+ }
+
+ private void deleteFile(final String path) throws Exception {
+ File file = new File(path);
+ if (file.exists()) {
+ if (!file.delete()) {
+ throw new Exception("Could not delete file at " + path);
+ }
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/hive/blob/8029e11b/beeline/src/test/resources/hive-site.xml
----------------------------------------------------------------------
diff --git a/beeline/src/test/resources/hive-site.xml b/beeline/src/test/resources/hive-site.xml
index 5f310d6..fdda94b 100644
--- a/beeline/src/test/resources/hive-site.xml
+++ b/beeline/src/test/resources/hive-site.xml
@@ -45,4 +45,9 @@
<value>${test.tmp.dir}/warehouse</value>
<description></description>
</property>
+ <property>
+ <name>test.data.files</name>
+ <value>${hive.root}/data/files</value>
+ <description></description>
+ </property>
</configuration>
http://git-wip-us.apache.org/repos/asf/hive/blob/8029e11b/beeline/src/test/resources/test-hs2-conn-conf-kerberos-http.xml
----------------------------------------------------------------------
diff --git a/beeline/src/test/resources/test-hs2-conn-conf-kerberos-http.xml b/beeline/src/test/resources/test-hs2-conn-conf-kerberos-http.xml
new file mode 100644
index 0000000..75f4fb8
--- /dev/null
+++ b/beeline/src/test/resources/test-hs2-conn-conf-kerberos-http.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
+<!--
+ 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.
+-->
+<configuration>
+<property>
+ <name>beeline.hs2.connection.hosts</name>
+ <value>localhost:10000</value>
+</property>
+<property>
+ <name>beeline.hs2.connection.principal</name>
+ <value>hive/dummy-hostname@domain.com</value>
+</property>
+<property>
+ <name>beeline.hs2.connection.ssl</name>
+ <value>true</value>
+</property>
+<property>
+ <name>beeline.hs2.connection.sslTrustStore</name>
+ <value>test/truststore</value>
+</property>
+<property>
+ <name>beeline.hs2.connection.trustStorePassword</name>
+ <value>testTruststorePassword</value>
+</property>
+<property>
+ <name>beeline.hs2.connection.transportMode</name>
+ <value>http</value>
+</property>
+<property>
+ <name>beeline.hs2.connection.httpPath</name>
+ <value>testHTTPPath</value>
+</property>
+</configuration>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/hive/blob/8029e11b/beeline/src/test/resources/test-hs2-conn-conf-kerberos-nossl.xml
----------------------------------------------------------------------
diff --git a/beeline/src/test/resources/test-hs2-conn-conf-kerberos-nossl.xml b/beeline/src/test/resources/test-hs2-conn-conf-kerberos-nossl.xml
new file mode 100644
index 0000000..dbceee5
--- /dev/null
+++ b/beeline/src/test/resources/test-hs2-conn-conf-kerberos-nossl.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
+<!--
+ 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.
+-->
+<configuration>
+<property>
+ <name>beeline.hs2.connection.hosts</name>
+ <value>localhost:10000</value>
+</property>
+<property>
+ <name>beeline.hs2.connection.principal</name>
+ <value>hive/dummy-hostname@domain.com</value>
+</property>
+<property>
+ <name>beeline.hs2.connection.ssl</name>
+ <value>false</value>
+</property>
+</configuration>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/hive/blob/8029e11b/beeline/src/test/resources/test-hs2-conn-conf-kerberos-ssl.xml
----------------------------------------------------------------------
diff --git a/beeline/src/test/resources/test-hs2-conn-conf-kerberos-ssl.xml b/beeline/src/test/resources/test-hs2-conn-conf-kerberos-ssl.xml
new file mode 100644
index 0000000..7dce56c
--- /dev/null
+++ b/beeline/src/test/resources/test-hs2-conn-conf-kerberos-ssl.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
+<!--
+ 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.
+-->
+<configuration>
+<property>
+ <name>beeline.hs2.connection.hosts</name>
+ <value>localhost:10000</value>
+</property>
+<property>
+ <name>beeline.hs2.connection.principal</name>
+ <value>hive/dummy-hostname@domain.com</value>
+</property>
+<property>
+ <name>beeline.hs2.connection.ssl</name>
+ <value>true</value>
+</property>
+<property>
+ <name>beeline.hs2.connection.sslTrustStore</name>
+ <value>test/truststore</value>
+</property>
+<property>
+ <name>beeline.hs2.connection.trustStorePassword</name>
+ <value>testTruststorePassword</value>
+</property>
+</configuration>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/hive/blob/8029e11b/beeline/src/test/resources/test-hs2-connection-conf-list.xml
----------------------------------------------------------------------
diff --git a/beeline/src/test/resources/test-hs2-connection-conf-list.xml b/beeline/src/test/resources/test-hs2-connection-conf-list.xml
new file mode 100644
index 0000000..6c022b1
--- /dev/null
+++ b/beeline/src/test/resources/test-hs2-connection-conf-list.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
+<!--
+ 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.
+-->
+<configuration>
+<property>
+ <name>beeline.hs2.connection.hosts</name>
+ <value>localhost:10000</value>
+</property>
+<property>
+ <name>beeline.hs2.connection.user</name>
+ <value>hive</value>
+</property>
+<property>
+ <name>beeline.hs2.connection.hiveconf</name>
+ <value>hive.cli.print.current.db=false</value>
+</property>
+<property>
+ <name>beeline.hs2.connection.hivevar</name>
+ <value>testVarName1=value1</value>
+</property>
+</configuration>
http://git-wip-us.apache.org/repos/asf/hive/blob/8029e11b/beeline/src/test/resources/test-hs2-connection-config-noauth.xml
----------------------------------------------------------------------
diff --git a/beeline/src/test/resources/test-hs2-connection-config-noauth.xml b/beeline/src/test/resources/test-hs2-connection-config-noauth.xml
new file mode 100644
index 0000000..7a858e0
--- /dev/null
+++ b/beeline/src/test/resources/test-hs2-connection-config-noauth.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
+<!--
+ 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.
+-->
+<configuration>
+<property>
+ <name>beeline.hs2.connection.hosts</name>
+ <value>localhost:10000</value>
+</property>
+<property>
+ <name>beeline.hs2.connection.user</name>
+ <value>hive</value>
+</property>
+</configuration>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/hive/blob/8029e11b/beeline/src/test/resources/test-hs2-connection-multi-conf-list.xml
----------------------------------------------------------------------
diff --git a/beeline/src/test/resources/test-hs2-connection-multi-conf-list.xml b/beeline/src/test/resources/test-hs2-connection-multi-conf-list.xml
new file mode 100644
index 0000000..7faae44
--- /dev/null
+++ b/beeline/src/test/resources/test-hs2-connection-multi-conf-list.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
+<!--
+ 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.
+-->
+<configuration>
+<property>
+ <name>beeline.hs2.connection.hosts</name>
+ <value>localhost:10000</value>
+</property>
+<property>
+ <name>beeline.hs2.connection.user</name>
+ <value>hive</value>
+</property>
+<property>
+ <name>beeline.hs2.connection.hiveconf</name>
+ <value>hive.cli.print.current.db=true, hive.cli.print.header=true</value>
+</property>
+<property>
+ <name>beeline.hs2.connection.hivevar</name>
+ <value>testVarName1=value1, testVarName2=value2</value>
+</property>
+</configuration>
+
http://git-wip-us.apache.org/repos/asf/hive/blob/8029e11b/beeline/src/test/resources/test-hs2-connection-zookeeper-config.xml
----------------------------------------------------------------------
diff --git a/beeline/src/test/resources/test-hs2-connection-zookeeper-config.xml b/beeline/src/test/resources/test-hs2-connection-zookeeper-config.xml
new file mode 100644
index 0000000..aa95b76
--- /dev/null
+++ b/beeline/src/test/resources/test-hs2-connection-zookeeper-config.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
+<!--
+ 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.
+-->
+<configuration>
+<property>
+ <name>beeline.hs2.connection.hosts</name>
+ <value>zk-node-1:10000,zk-node-2:10001,zk-node-3:10004</value>
+</property>
+<property>
+ <name>beeline.hs2.connection.serviceDiscoveryMode</name>
+ <value>zookeeper</value>
+</property>
+<property>
+ <name>beeline.hs2.connection.zooKeeperNamespace</name>
+ <value>hiveserver2</value>
+</property>
+</configuration>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/hive/blob/8029e11b/itests/hive-unit/src/test/java/org/apache/hive/beeline/hs2connection/TestBeelineConnectionUsingHiveSite.java
----------------------------------------------------------------------
diff --git a/itests/hive-unit/src/test/java/org/apache/hive/beeline/hs2connection/TestBeelineConnectionUsingHiveSite.java b/itests/hive-unit/src/test/java/org/apache/hive/beeline/hs2connection/TestBeelineConnectionUsingHiveSite.java
new file mode 100644
index 0000000..fe77667
--- /dev/null
+++ b/itests/hive-unit/src/test/java/org/apache/hive/beeline/hs2connection/TestBeelineConnectionUsingHiveSite.java
@@ -0,0 +1,109 @@
+/**
+ * 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.hive.beeline.hs2connection;
+
+import java.io.File;
+
+import org.apache.hadoop.hive.conf.HiveConf.ConfVars;
+import org.apache.hive.beeline.hs2connection.HS2ConnectionFileParser;
+import org.apache.hive.jdbc.miniHS2.MiniHS2;
+import org.junit.Test;
+
+public class TestBeelineConnectionUsingHiveSite extends TestBeelineWithHS2ConnectionFile {
+ @Test
+ public void testBeelineConnectionHttp() throws Exception {
+ setupHs2();
+ String path = createDefaultHs2ConnectionFile();
+ testBeeLineConnection(path, new String[] { "-e", "show tables;" }, tableName);
+ }
+
+ @Test
+ public void testBeelineConnectionSSL() throws Exception {
+ setupSSLHs2();
+ String path = createDefaultHs2ConnectionFile();
+ testBeeLineConnection(path, new String[] { "-e", "show tables;" }, tableName);
+ }
+
+ @Test
+ public void testBeelineConnectionNoAuth() throws Exception {
+ setupNoAuthHs2();
+ String path = createDefaultHs2ConnectionFile();
+ testBeeLineConnection(path, new String[] { "-e", "show tables;" }, tableName);
+ }
+
+ /*
+ * tests if the beeline behaves like default mode if there is no user-specific connection
+ * configuration file
+ */
+ @Test
+ public void testBeelineWithNoConnectionFile() throws Exception {
+ setupNoAuthHs2();
+ testBeeLineConnection(null, new String[] { "-e", "show tables;" }, "no current connection");
+ }
+
+ @Test
+ public void testBeelineUsingArgs() throws Exception {
+ setupNoAuthHs2();
+ String url = miniHS2.getBaseJdbcURL() + "default";
+ String args[] = new String[] { "-u", url, "-n", System.getProperty("user.name"), "-p", "foo",
+ "-e", "show tables;" };
+ testBeeLineConnection(null, args, tableName);
+ }
+
+ private void setupNoAuthHs2() throws Exception {
+ // use default configuration for no-auth mode
+ miniHS2.start(confOverlay);
+ createTable();
+ }
+
+ private void setupSSLHs2() throws Exception {
+ confOverlay.put(ConfVars.HIVE_SERVER2_USE_SSL.varname, "true");
+ confOverlay.put(ConfVars.HIVE_SERVER2_SSL_KEYSTORE_PATH.varname,
+ dataFileDir + File.separator + LOCALHOST_KEY_STORE_NAME);
+ confOverlay.put(ConfVars.HIVE_SERVER2_SSL_KEYSTORE_PASSWORD.varname,
+ KEY_STORE_TRUST_STORE_PASSWORD);
+ miniHS2.start(confOverlay);
+ createTable();
+ System.setProperty(JAVA_TRUST_STORE_PROP, dataFileDir + File.separator + TRUST_STORE_NAME);
+ System.setProperty(JAVA_TRUST_STORE_PASS_PROP, KEY_STORE_TRUST_STORE_PASSWORD);
+ }
+
+ @Override
+ protected MiniHS2 getNewMiniHS2() throws Exception {
+ return new MiniHS2(hiveConf, MiniHS2.MiniClusterType.DFS_ONLY, true);
+ }
+
+ private void setupHs2() throws Exception {
+ confOverlay.put(ConfVars.HIVE_SERVER2_TRANSPORT_MODE.varname, HS2_HTTP_MODE);
+ confOverlay.put(ConfVars.HIVE_SERVER2_THRIFT_HTTP_PATH.varname, HS2_HTTP_ENDPOINT);
+ confOverlay.put(ConfVars.HIVE_SERVER2_ENABLE_DOAS.varname, "true");
+ miniHS2.start(confOverlay);
+ createTable();
+ }
+
+ private String createDefaultHs2ConnectionFile() throws Exception {
+ Hs2ConnectionXmlConfigFileWriter writer = new Hs2ConnectionXmlConfigFileWriter();
+ String baseJdbcURL = miniHS2.getBaseJdbcURL();
+ System.out.println(baseJdbcURL);
+ writer.writeProperty(HS2ConnectionFileParser.BEELINE_CONNECTION_PROPERTY_PREFIX + "user",
+ System.getProperty("user.name"));
+ writer.writeProperty(HS2ConnectionFileParser.BEELINE_CONNECTION_PROPERTY_PREFIX + "password", "foo");
+ writer.close();
+ return writer.path();
+ }
+}
http://git-wip-us.apache.org/repos/asf/hive/blob/8029e11b/itests/hive-unit/src/test/java/org/apache/hive/beeline/hs2connection/TestBeelineWithHS2ConnectionFile.java
----------------------------------------------------------------------
diff --git a/itests/hive-unit/src/test/java/org/apache/hive/beeline/hs2connection/TestBeelineWithHS2ConnectionFile.java b/itests/hive-unit/src/test/java/org/apache/hive/beeline/hs2connection/TestBeelineWithHS2ConnectionFile.java
new file mode 100644
index 0000000..32e9afd
--- /dev/null
+++ b/itests/hive-unit/src/test/java/org/apache/hive/beeline/hs2connection/TestBeelineWithHS2ConnectionFile.java
@@ -0,0 +1,214 @@
+/**
+ * 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.hive.beeline.hs2connection;
+
+import static org.junit.Assert.assertFalse;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
+import java.sql.DriverManager;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hive.conf.HiveConf;
+import org.apache.hadoop.hive.conf.HiveConf.ConfVars;
+import org.apache.hive.beeline.BeeLine;
+import org.apache.hive.beeline.hs2connection.HS2ConnectionFileParser;
+import org.apache.hive.beeline.hs2connection.HiveSiteHS2ConnectionFileParser;
+import org.apache.hive.beeline.hs2connection.UserHS2ConnectionFileParser;
+import org.apache.hive.jdbc.miniHS2.MiniHS2;
+import org.apache.hive.service.cli.CLIServiceClient;
+import org.apache.hive.service.cli.HiveSQLException;
+import org.apache.hive.service.cli.OperationHandle;
+import org.apache.hive.service.cli.RowSet;
+import org.apache.hive.service.cli.SessionHandle;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+
+public abstract class TestBeelineWithHS2ConnectionFile {
+ protected MiniHS2 miniHS2;
+ protected HiveConf hiveConf = new HiveConf();
+ protected final String tableName = "testBeelineTable";
+ protected String dataFileDir = hiveConf.get("test.data.files");
+ protected static final String LOCALHOST_KEY_STORE_NAME = "keystore.jks";
+ protected static final String TRUST_STORE_NAME = "truststore.jks";
+ protected static final String KEY_STORE_TRUST_STORE_PASSWORD = "HiveJdbc";
+ protected static final String HS2_HTTP_MODE = "http";
+ protected static final String HS2_HTTP_ENDPOINT = "cliservice";
+ private final String fileLocation =
+ System.getProperty("java.io.tmpdir") + "testHs2ConnectionConfig.xml";
+ protected static final String JAVA_TRUST_STORE_PROP = "javax.net.ssl.trustStore";
+ protected static final String JAVA_TRUST_STORE_PASS_PROP = "javax.net.ssl.trustStorePassword";
+
+ protected Map<String, String> confOverlay = new HashMap<>();
+
+ protected class TestBeeLine extends BeeLine {
+ UserHS2ConnectionFileParser testHs2ConfigFileManager;
+ ByteArrayOutputStream os;
+
+ TestBeeLine(List<String> defaultHS2ConnectionFiles) {
+ testHs2ConfigFileManager = new UserHS2ConnectionFileParser(defaultHS2ConnectionFiles);
+ os = new ByteArrayOutputStream();
+ PrintStream beelineOutputStream = new PrintStream(os);
+ setOutputStream(beelineOutputStream);
+ setErrorStream(beelineOutputStream);
+ }
+
+ TestBeeLine() {
+ testHs2ConfigFileManager = new UserHS2ConnectionFileParser(null);
+ os = new ByteArrayOutputStream();
+ PrintStream beelineOutputStream = new PrintStream(os);
+ setOutputStream(beelineOutputStream);
+ setErrorStream(beelineOutputStream);
+ }
+
+ public String getOutput() throws UnsupportedEncodingException {
+ return os.toString("UTF8");
+ }
+
+ @Override
+ public HS2ConnectionFileParser getUserHS2ConnFileParser() {
+ return testHs2ConfigFileManager;
+ }
+
+ @Override
+ public HS2ConnectionFileParser getHiveSiteHS2ConnectionFileParser() {
+ HiveSiteHS2ConnectionFileParser ret = new HiveSiteHS2ConnectionFileParser();
+ ret.setHiveConf(miniHS2.getHiveConf());
+ return ret;
+ }
+ }
+
+ /*
+ * Wrapper class to write a HS2ConnectionConfig file
+ */
+ protected class Hs2ConnectionXmlConfigFileWriter {
+ private final PrintWriter writer;
+ private final File file;
+ private final Configuration conf;
+
+ protected Hs2ConnectionXmlConfigFileWriter() throws IOException {
+ file = new File(fileLocation);
+ conf = new Configuration(false);
+ try {
+ if (file.exists()) {
+ file.delete();
+ }
+ file.createNewFile();
+ writer = new PrintWriter(file.getAbsolutePath(), "UTF-8");
+ } finally {
+ file.deleteOnExit();
+ }
+ }
+
+ protected void writeProperty(String key, String value) {
+ conf.set(key, value);
+ }
+
+ protected String path() {
+ return file.getAbsolutePath();
+ }
+
+ protected void close() throws IOException {
+ try {
+ conf.writeXml(writer);
+ } finally {
+ writer.close();
+ }
+ }
+ }
+
+ @BeforeClass
+ public static void beforeTest() throws Exception {
+ Class.forName(MiniHS2.getJdbcDriverName());
+ }
+
+ @Before
+ public void before() throws Exception {
+ DriverManager.setLoginTimeout(0);
+ if (!System.getProperty("test.data.files", "").isEmpty()) {
+ dataFileDir = System.getProperty("test.data.files");
+ }
+ dataFileDir = dataFileDir.replace('\\', '/').replace("c:", "");
+ hiveConf = new HiveConf();
+ miniHS2 = getNewMiniHS2();
+ confOverlay = new HashMap<String, String>();
+ confOverlay.put(ConfVars.HIVE_SUPPORT_CONCURRENCY.varname, "false");
+ confOverlay.put(ConfVars.HIVE_SERVER2_TRANSPORT_MODE.varname, "binary");
+ }
+
+ protected MiniHS2 getNewMiniHS2() throws Exception {
+ return new MiniHS2(hiveConf);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ if (miniHS2 != null && miniHS2.isStarted()) {
+ miniHS2.stop();
+ }
+ miniHS2 = null;
+ System.clearProperty(JAVA_TRUST_STORE_PROP);
+ System.clearProperty(JAVA_TRUST_STORE_PASS_PROP);
+ }
+
+ protected void createTable() throws HiveSQLException {
+ CLIServiceClient serviceClient = miniHS2.getServiceClient();
+ SessionHandle sessHandle = serviceClient.openSession("foo", "bar");
+ serviceClient.executeStatement(sessHandle, "DROP TABLE IF EXISTS " + tableName, confOverlay);
+ serviceClient.executeStatement(sessHandle, "CREATE TABLE " + tableName + " (id INT)",
+ confOverlay);
+ OperationHandle opHandle =
+ serviceClient.executeStatement(sessHandle, "SHOW TABLES", confOverlay);
+ RowSet rowSet = serviceClient.fetchResults(opHandle);
+ assertFalse(rowSet.numRows() == 0);
+ }
+
+ protected String testBeeLineConnection(String path, String[] beelineArgs,
+ String expectedOutput) throws IOException {
+ TestBeeLine beeLine = null;
+ try {
+ if(path != null) {
+ List<String> testLocations = new ArrayList<>();
+ testLocations.add(path);
+ beeLine = new TestBeeLine(testLocations);
+ } else {
+ beeLine = new TestBeeLine();
+ }
+ beeLine.begin(beelineArgs, null);
+ String output = beeLine.getOutput();
+ System.out.println(output);
+ Assert.assertNotNull(output);
+ Assert.assertTrue("Output " + output + " does not contain " + expectedOutput,
+ output.toLowerCase().contains(expectedOutput.toLowerCase()));
+ return output;
+ } finally {
+ if (beeLine != null) {
+ beeLine.close();
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/hive/blob/8029e11b/itests/hive-unit/src/test/java/org/apache/hive/beeline/hs2connection/TestBeelineWithUserHs2ConnectionFile.java
----------------------------------------------------------------------
diff --git a/itests/hive-unit/src/test/java/org/apache/hive/beeline/hs2connection/TestBeelineWithUserHs2ConnectionFile.java b/itests/hive-unit/src/test/java/org/apache/hive/beeline/hs2connection/TestBeelineWithUserHs2ConnectionFile.java
new file mode 100644
index 0000000..0f86186
--- /dev/null
+++ b/itests/hive-unit/src/test/java/org/apache/hive/beeline/hs2connection/TestBeelineWithUserHs2ConnectionFile.java
@@ -0,0 +1,129 @@
+/**
+ * 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.hive.beeline.hs2connection;
+
+import java.io.File;
+import java.net.URI;
+
+import org.apache.hadoop.hive.conf.HiveConf.ConfVars;
+import org.apache.hive.beeline.hs2connection.HS2ConnectionFileParser;
+import org.junit.Test;
+
+public class TestBeelineWithUserHs2ConnectionFile extends TestBeelineWithHS2ConnectionFile {
+
+ @Test
+ public void testBeelineConnectionHttp() throws Exception {
+ setupHttpHs2();
+ String path = createHttpHs2ConnectionFile();
+ testBeeLineConnection(path, new String[] { "-e", "show tables;" }, tableName);
+ }
+
+ private void setupHttpHs2() throws Exception {
+ confOverlay.put(ConfVars.HIVE_SERVER2_TRANSPORT_MODE.varname, HS2_HTTP_MODE);
+ confOverlay.put(ConfVars.HIVE_SERVER2_THRIFT_HTTP_PATH.varname, HS2_HTTP_ENDPOINT);
+ confOverlay.put(ConfVars.HIVE_SERVER2_ENABLE_DOAS.varname, "true");
+ miniHS2.start(confOverlay);
+ createTable();
+ }
+
+ private String createHttpHs2ConnectionFile() throws Exception {
+ Hs2ConnectionXmlConfigFileWriter writer = new Hs2ConnectionXmlConfigFileWriter();
+ String baseJdbcURL = miniHS2.getBaseJdbcURL();
+
+ URI uri = new URI(baseJdbcURL.substring(5));
+ writer.writeProperty(HS2ConnectionFileParser.BEELINE_CONNECTION_PROPERTY_PREFIX + "hosts",
+ uri.getHost() + ":" + uri.getPort());
+ writer.writeProperty(HS2ConnectionFileParser.BEELINE_CONNECTION_PROPERTY_PREFIX + "user",
+ System.getProperty("user.name"));
+ writer.writeProperty(HS2ConnectionFileParser.BEELINE_CONNECTION_PROPERTY_PREFIX + "password",
+ "foo");
+ writer.writeProperty(
+ HS2ConnectionFileParser.BEELINE_CONNECTION_PROPERTY_PREFIX + "transportMode",
+ HS2_HTTP_MODE);
+ writer.writeProperty(HS2ConnectionFileParser.BEELINE_CONNECTION_PROPERTY_PREFIX + "httpPath",
+ HS2_HTTP_ENDPOINT);
+ writer.close();
+ return writer.path();
+ }
+
+ @Test
+ public void testBeelineConnectionNoAuth() throws Exception {
+ setupNoAuthConfHS2();
+ String path = createNoAuthHs2ConnectionFile();
+ testBeeLineConnection(path, new String[] { "-e", "show tables;" }, tableName);
+ }
+
+ private void setupNoAuthConfHS2() throws Exception {
+ // use default configuration for no-auth mode
+ miniHS2.start(confOverlay);
+ createTable();
+ }
+
+ private String createNoAuthHs2ConnectionFile() throws Exception {
+ Hs2ConnectionXmlConfigFileWriter writer = new Hs2ConnectionXmlConfigFileWriter();
+ String baseJdbcURL = miniHS2.getBaseJdbcURL();
+ URI uri = new URI(baseJdbcURL.substring(5));
+ writer.writeProperty(HS2ConnectionFileParser.BEELINE_CONNECTION_PROPERTY_PREFIX + "hosts",
+ uri.getHost() + ":" + uri.getPort());
+ writer.writeProperty(HS2ConnectionFileParser.BEELINE_CONNECTION_PROPERTY_PREFIX + "user",
+ System.getProperty("user.name"));
+ writer.writeProperty(HS2ConnectionFileParser.BEELINE_CONNECTION_PROPERTY_PREFIX + "password",
+ "foo");
+ writer.close();
+ return writer.path();
+ }
+
+ @Test
+ public void testBeelineConnectionSSL() throws Exception {
+ setupSslHs2();
+ String path = createSSLHs2ConnectionFile();
+ testBeeLineConnection(path, new String[] { "-e", "show tables;" }, tableName);
+ }
+
+ private String createSSLHs2ConnectionFile() throws Exception {
+ Hs2ConnectionXmlConfigFileWriter writer = new Hs2ConnectionXmlConfigFileWriter();
+ String baseJdbcURL = miniHS2.getBaseJdbcURL();
+ URI uri = new URI(baseJdbcURL.substring(5));
+ writer.writeProperty(HS2ConnectionFileParser.BEELINE_CONNECTION_PROPERTY_PREFIX + "hosts",
+ uri.getHost() + ":" + uri.getPort());
+ writer.writeProperty(HS2ConnectionFileParser.BEELINE_CONNECTION_PROPERTY_PREFIX + "user",
+ System.getProperty("user.name"));
+ writer.writeProperty(HS2ConnectionFileParser.BEELINE_CONNECTION_PROPERTY_PREFIX + "password",
+ "foo");
+ writer.writeProperty(HS2ConnectionFileParser.BEELINE_CONNECTION_PROPERTY_PREFIX + "ssl",
+ "true");
+ writer.writeProperty(
+ HS2ConnectionFileParser.BEELINE_CONNECTION_PROPERTY_PREFIX + "trustStorePassword",
+ KEY_STORE_TRUST_STORE_PASSWORD);
+ writer.writeProperty(
+ HS2ConnectionFileParser.BEELINE_CONNECTION_PROPERTY_PREFIX + "sslTrustStore",
+ dataFileDir + File.separator + TRUST_STORE_NAME);
+ writer.close();
+ return writer.path();
+ }
+
+ private void setupSslHs2() throws Exception {
+ confOverlay.put(ConfVars.HIVE_SERVER2_USE_SSL.varname, "true");
+ confOverlay.put(ConfVars.HIVE_SERVER2_SSL_KEYSTORE_PATH.varname,
+ dataFileDir + File.separator + LOCALHOST_KEY_STORE_NAME);
+ confOverlay.put(ConfVars.HIVE_SERVER2_SSL_KEYSTORE_PASSWORD.varname,
+ KEY_STORE_TRUST_STORE_PASSWORD);
+ miniHS2.start(confOverlay);
+ createTable();
+ }
+}