public static JdbcConnectionParams extractURLComponents()

in kyuubi-hive-jdbc/src/main/java/org/apache/kyuubi/jdbc/hive/Utils.java [231:410]


  public static JdbcConnectionParams extractURLComponents(String uri, Properties info)
      throws JdbcUriParseException {
    JdbcConnectionParams connParams = new JdbcConnectionParams();

    // The JDBC URI now supports specifying multiple host:port if dynamic service discovery is
    // configured on HiveServer2 (like: host1:port1,host2:port2,host3:port3)
    // We'll extract the authorities (host:port combo) from the URI, extract session vars, hive
    // confs & hive vars by parsing it as a Java URI.
    String authorityFromClientJdbcURL = getAuthorityFromJdbcURL(uri);
    if (authorityFromClientJdbcURL.isEmpty()) {
      // Given uri of the form:
      // jdbc:hive2:///dbName;sess_var_list?hive_conf_list#hive_var_list
      authorityFromClientJdbcURL = "localhost:10009";
      String urlPrefix = getMatchedUrlPrefix(uri);
      uri = uri.replace(urlPrefix, urlPrefix + authorityFromClientJdbcURL);
    }
    connParams.setSuppliedURLAuthority(authorityFromClientJdbcURL);
    uri = uri.replaceFirst(authorityFromClientJdbcURL, dummyAuthorityString);

    // Now parse the connection uri with dummy authority
    URI jdbcURI = URI.create(uri.substring(URI_JDBC_PREFIX.length()));

    // key=value pattern
    Pattern pattern = Pattern.compile("([^;]*)=([^;]*);?");

    // dbname and session settings
    String sessVars = jdbcURI.getPath();
    if ((sessVars != null) && !sessVars.isEmpty()) {
      String dbName = "";
      String catalogName = "";
      // removing leading '/' returned by getPath()
      sessVars = sessVars.substring(1);
      if (!sessVars.contains(";")) {
        if (sessVars.contains("/")) {
          catalogName = sessVars.substring(0, sessVars.indexOf('/'));
          dbName = sessVars.substring(sessVars.indexOf('/') + 1);
        } else {
          // only dbname is provided
          dbName = sessVars;
        }
      } else {
        // we have dbname followed by session parameters
        String catalogAndDb = sessVars.substring(0, sessVars.indexOf(';'));
        if (catalogAndDb.contains("/")) {
          catalogName = catalogAndDb.substring(0, catalogAndDb.indexOf('/'));
          dbName = catalogAndDb.substring(catalogAndDb.indexOf('/') + 1);
        } else {
          // only dbname is provided
          dbName = catalogAndDb;
        }
        sessVars = sessVars.substring(sessVars.indexOf(';') + 1);
        Matcher sessMatcher = pattern.matcher(sessVars);
        while (sessMatcher.find()) {
          if (connParams.getSessionVars().put(sessMatcher.group(1), sessMatcher.group(2)) != null) {
            throw new JdbcUriParseException(
                "Bad URL format: Multiple values for property " + sessMatcher.group(1));
          }
        }
      }
      if (!catalogName.isEmpty()) {
        connParams.setCatalogName(catalogName);
      }
      if (!dbName.isEmpty()) {
        connParams.setDbName(dbName);
      }
    }

    Pattern confPattern = Pattern.compile("([^;]*)([^;]*);?");

    // parse hive conf settings
    String confStr = jdbcURI.getQuery();
    if (confStr != null) {
      Matcher confMatcher = confPattern.matcher(confStr);
      while (confMatcher.find()) {
        String connParam = confMatcher.group(1);
        if (StringUtils.isNotBlank(connParam) && connParam.contains("=")) {
          int symbolIndex = connParam.indexOf('=');
          connParams
              .getHiveConfs()
              .put(connParam.substring(0, symbolIndex), connParam.substring(symbolIndex + 1));
        }
      }
    }

    // parse hive var settings
    String varStr = jdbcURI.getFragment();
    if (varStr != null) {
      Matcher varMatcher = pattern.matcher(varStr);
      while (varMatcher.find()) {
        connParams.getHiveVars().put(varMatcher.group(1), varMatcher.group(2));
      }
    }

    // Apply configs supplied in the JDBC connection properties object
    for (Map.Entry<Object, Object> kv : info.entrySet()) {
      if ((kv.getKey() instanceof String)) {
        String key = (String) kv.getKey();
        if (key.startsWith(HIVE_VAR_PREFIX)) {
          connParams
              .getHiveVars()
              .put(key.substring(HIVE_VAR_PREFIX.length()), info.getProperty(key));
        } else if (key.startsWith(HIVE_CONF_PREFIX)) {
          connParams
              .getHiveConfs()
              .put(key.substring(HIVE_CONF_PREFIX.length()), info.getProperty(key));
        }
      }
    }
    if (!connParams.getSessionVars().containsKey(CLIENT_PROTOCOL_VERSION)) {
      if (info.containsKey(CLIENT_PROTOCOL_VERSION)) {
        connParams
            .getSessionVars()
            .put(CLIENT_PROTOCOL_VERSION, info.getProperty(CLIENT_PROTOCOL_VERSION));
      }
    }
    // Extract user/password from JDBC connection properties if its not supplied
    // in the connection URL
    if (!connParams.getSessionVars().containsKey(AUTH_USER)) {
      if (info.containsKey(AUTH_USER)) {
        connParams.getSessionVars().put(AUTH_USER, info.getProperty(AUTH_USER));
      }
      if (info.containsKey(AUTH_PASSWD)) {
        connParams.getSessionVars().put(AUTH_PASSWD, info.getProperty(AUTH_PASSWD));
      }
    }

    if (!connParams.getSessionVars().containsKey(AUTH_PASSWD)) {
      if (info.containsKey(AUTH_USER)) {
        connParams.getSessionVars().put(AUTH_USER, info.getProperty(AUTH_USER));
      }
      if (info.containsKey(AUTH_PASSWD)) {
        connParams.getSessionVars().put(AUTH_PASSWD, info.getProperty(AUTH_PASSWD));
      }
    }

    if (info.containsKey(AUTH_TYPE)) {
      connParams.getSessionVars().put(AUTH_TYPE, info.getProperty(AUTH_TYPE));
    }

    String authorityStr = connParams.getSuppliedURLAuthority();
    // If we're using ZooKeeper, the final host, port will be read from ZooKeeper
    // (in a different method call). Therefore, we put back the original authority string
    // (which basically is the ZooKeeper ensemble) back in the uri
    if (ZooKeeperHiveClientHelper.isZkDynamicDiscoveryMode(connParams.getSessionVars())) {
      uri = uri.replace(dummyAuthorityString, authorityStr);
      // Set ZooKeeper ensemble in connParams for later use
      connParams.setZooKeeperEnsemble(authorityStr);
    } else {
      URI jdbcBaseURI = URI.create(URI_HIVE_PREFIX + "//" + authorityStr);
      // Check to prevent unintentional use of embedded mode. A missing "/"
      // to separate the 'path' portion of URI can result in this.
      // The missing "/" common typo while using secure mode, eg of such url -
      // jdbc:hive2://localhost:10000;principal=hive/HiveServer2Host@YOUR-REALM.COM
      if (jdbcBaseURI.getAuthority() != null) {
        String host = jdbcBaseURI.getHost();
        int port = jdbcBaseURI.getPort();
        if (host == null) {
          throw new JdbcUriParseException(
              "Bad URL format. Hostname not found "
                  + " in authority part of the url: "
                  + jdbcBaseURI.getAuthority()
                  + ". Are you missing a '/' after the hostname ?");
        }
        // Set the port to default value; we do support jdbc url like:
        // jdbc:hive2://localhost/db
        if (port <= 0) {
          port = Integer.parseInt(Utils.DEFAULT_PORT);
        }
        connParams.setHost(host);
        connParams.setPort(port);
      }
      // We check for invalid host, port while configuring connParams with configureConnParams()
      authorityStr = connParams.getHost() + ":" + connParams.getPort();
      LOG.debug("Resolved authority: " + authorityStr);
      uri = uri.replace(dummyAuthorityString, authorityStr);
    }

    connParams.setJdbcUriString(uri);
    return connParams;
  }