This is an automated email from the ASF dual-hosted git repository.

difin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hive.git


The following commit(s) were added to refs/heads/master by this push:
     new fc7fe353a4a HIVE-28782: Avoid unsafe splits on URIs that might contain 
IPv6 literals (#5729) (Dmitriy Fingerman, reviewed by Ayush Saxena, Kokila N)
fc7fe353a4a is described below

commit fc7fe353a4a51d360ef799ede81e3770043b594d
Author: Dmitriy Fingerman <[email protected]>
AuthorDate: Wed Apr 9 10:10:19 2025 -0400

    HIVE-28782: Avoid unsafe splits on URIs that might contain IPv6 literals 
(#5729) (Dmitriy Fingerman, reviewed by Ayush Saxena, Kokila N)
    
    HIVE-28782: Avoid unsafe splits on URIs that might contain IPv6 literals
---
 .../java/org/apache/hive/common/IPStackUtils.java  |  86 ++++++++++++++
 .../org/apache/hive/common/IPStackUtilsTest.java   |  90 +++++++++------
 .../hive/jdbc/ZooKeeperHiveClientHelper.java       |  10 +-
 .../hive/jdbc/ZooKeeperHiveClientHelperTest.java   | 120 ++++++++++++++++++++
 .../hadoop/hive/ql/lockmgr/HiveLockObject.java     |   7 +-
 .../hadoop/hive/ql/lockmgr/TestHiveLockObject.java | 123 +++++++++++++++------
 .../service/server/HS2ActivePassiveHARegistry.java |   8 +-
 7 files changed, 366 insertions(+), 78 deletions(-)

diff --git a/common/src/java/org/apache/hive/common/IPStackUtils.java 
b/common/src/java/org/apache/hive/common/IPStackUtils.java
index 7b24b8a0781..949b6f14be1 100644
--- a/common/src/java/org/apache/hive/common/IPStackUtils.java
+++ b/common/src/java/org/apache/hive/common/IPStackUtils.java
@@ -20,6 +20,8 @@
 
 import com.google.common.annotations.VisibleForTesting;
 import io.netty.util.NetUtil;
+import org.apache.commons.lang3.StringUtils;
+
 import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.util.Arrays;
@@ -219,4 +221,88 @@ public static String transformToIPv6(String ipv4, int 
port) {
       return ipv4;
     }
   }
+
+  /**
+   * Splits a given input string representing a Hostname or an IP address and 
port into an `HostPort` object.
+   * The input string must be in the format of IPv4/IPv6/[IPv6]/hostname:port.
+   * 
+   * @param input The input string containing the Hostname/IP address and 
port, in the format 
+   *              "IPv4:port", "[IPv6]:port", "IPv6:port", or "hostname:port".
+   * @return A {@link HostPort} object containing the parsed IP address and 
port number.
+   * @throws IllegalArgumentException If the input format is invalid, if the 
host is null or empty,
+   *                                  or if the port number is invalid.
+   */
+  public static HostPort getHostAndPort(String input) {
+    String host;
+    int port;
+
+    if (StringUtils.isEmpty(input)) {
+      throw new IllegalArgumentException("Input string is null or empty");
+    }
+
+    // Check if the input contains a colon, which separates the host and port
+    int colonIndex = input.lastIndexOf(':');
+    if (colonIndex == -1) {
+      throw new IllegalArgumentException("Input does not contain a port.");
+    }
+
+    // Extract the host and port parts
+    host = input.substring(0, colonIndex);
+    port = getPort(input.substring(colonIndex + 1));
+
+    // Check if the host is not null or empty
+    if (StringUtils.isEmpty(host) || host.equals("[]")) {
+      throw new IllegalArgumentException("Host address is null or empty.");
+    }
+
+    // Handle IPv6 addresses enclosed in square brackets (e.g., [IPv6]:port)
+    if (host.startsWith("[") && host.endsWith("]")) {
+      host = host.substring(1, host.length() - 1); // Remove the square 
brackets
+    }
+
+    return new HostPort(host, port);
+  }
+
+  /**
+   * Returns an integer representation of the port number.
+   * Also validates whether the given string represents a valid port number.
+   * A valid port number is an integer between 0 and 65535 inclusive.
+   *
+   * @param portString The string representing the port number.
+   * @return {@code int} the port number.
+   */
+  public static int getPort(String portString) {
+    if (StringUtils.isEmpty(portString)) {
+      throw new IllegalArgumentException("port is null or empty");
+    }
+
+    int port = Integer.parseInt(portString);
+    validatePort(port);
+    return port;
+  }
+  
+  private static void validatePort(int port) {
+    if (port < 0 || port > 65535) {
+      throw new IllegalArgumentException("Port number out of range 
(0-65535).");
+    }
+  }
+
+  public static class HostPort {
+
+    private final String hostname;
+    private final int port;
+
+    public HostPort(String hostname, int port) {
+      this.hostname = hostname;
+      this.port = port;
+    }
+
+    public String getHostname() {
+      return hostname;
+    }
+
+    public int getPort() {
+      return port;
+    }
+  }
 }
diff --git a/common/src/test/org/apache/hive/common/IPStackUtilsTest.java 
b/common/src/test/org/apache/hive/common/IPStackUtilsTest.java
index 4c89c0e9069..7b289ee275f 100644
--- a/common/src/test/org/apache/hive/common/IPStackUtilsTest.java
+++ b/common/src/test/org/apache/hive/common/IPStackUtilsTest.java
@@ -79,34 +79,12 @@ void testIPv4WildcardWhenIPv6IsNotPreferred() {
   }
 
   @Test
-  void testConcatHostPortIPv4Host() {
+  void testConcatHostPort() {
     assertEquals("192.168.1.1:8080", 
IPStackUtils.concatHostPort("192.168.1.1", 8080));
-  }
-
-  @Test
-  void testConcatHostPortIPv6Host() {
     assertEquals("[2001:db8::1]:8080", 
IPStackUtils.concatHostPort("2001:db8::1", 8080));
-  }
-
-  @Test
-  void testConcatHostPortIPv6Loopback() {
     assertEquals("[::1]:9090", IPStackUtils.concatHostPort("::1", 9090));
-  }
-
-  @Test
-  void testConcatHostPortHostname() {
     assertEquals("example.com:443", IPStackUtils.concatHostPort("example.com", 
443));
   }
-
-  @Test
-  void testConcatHostPortLoobackIPv4() {
-    assertEquals("127.0.0.1:3306", IPStackUtils.concatHostPort("127.0.0.1", 
3306));
-  }
-
-  @Test
-  void testConcatHostPortLoopbackIPv6() {
-    assertEquals("[::1]:3306", IPStackUtils.concatHostPort("::1", 3306));
-  }
   
   @Test
   void testWildcardWhenIPv4StackIsForcedAndIPv4WildcardProvided() {
@@ -164,20 +142,68 @@ void 
testWildcardWhenIPv6IsNotPreferredAndIPv6WildcardProvided() {
   }
 
   @Test
-  void testWildcardWhenNonWildcardIPv4AddressProvided() {
-    String result = IPStackUtils.adaptWildcardAddress("192.168.1.1");
-    assertEquals("192.168.1.1", result);
+  void testAdaptWildcardAddress() {
+    assertEquals("192.168.1.1", 
IPStackUtils.adaptWildcardAddress("192.168.1.1"));
+    assertEquals("2001:db8::1", 
IPStackUtils.adaptWildcardAddress("2001:db8::1"));
+    assertEquals("example.com", 
IPStackUtils.adaptWildcardAddress("example.com"));
+  }
+
+    // Test cases for getHostAndPort method
+
+  @Test
+  void testGetHostAndPortWithIPv4() {
+    IPStackUtils.HostPort result = 
IPStackUtils.getHostAndPort("192.168.1.1:8080");
+    assertEquals("192.168.1.1", result.getHostname());
+    assertEquals(8080, result.getPort());
+  }
+
+  @Test
+  void testGetHostAndPortWithValidIPv6WithSquaredBrackets() {
+    IPStackUtils.HostPort result = 
IPStackUtils.getHostAndPort("[2001:0db8::1]:8080");
+    assertEquals("2001:0db8::1", result.getHostname());
+    assertEquals(8080, result.getPort());
+  }
+
+  @Test
+  void testGetHostAndPortWithValidIPv6WithoutSquaredBrackets() {
+    IPStackUtils.HostPort result = 
IPStackUtils.getHostAndPort("2001:0db8::1:8080");
+    assertEquals("2001:0db8::1", result.getHostname());
+    assertEquals(8080, result.getPort());
+  }
+
+  @Test
+  void testGetHostAndPortWithHostname() {
+    IPStackUtils.HostPort result = 
IPStackUtils.getHostAndPort("example.com:80");
+    assertEquals("example.com", result.getHostname());
+    assertEquals(80, result.getPort());
   }
 
   @Test
-  void testWildcardWhenNonWildcardIPv6AddressProvided() {
-    String result = IPStackUtils.adaptWildcardAddress("2001:db8::1");
-    assertEquals("2001:db8::1", result);
+  void testGetHostPortWithInvalidAndPort() {
+    assertThrows(IllegalArgumentException.class, () -> 
IPStackUtils.getHostAndPort("192.168.1.1:70000"),
+        "Port number out of range (0-65535).");
+    assertThrows(IllegalArgumentException.class, () -> 
IPStackUtils.getHostAndPort("192.168.1.1"),
+        "Input does not contain a port.");
+    assertThrows(IllegalArgumentException.class, () -> 
IPStackUtils.getHostAndPort(":8080"),
+        "Host address is null or empty.");
+  }
+
+  // Test cases for getPort method
+
+  @Test
+  void testGetPort() {
+    assertEquals(8080, IPStackUtils.getPort("8080"));
+    assertEquals(65535, IPStackUtils.getPort("65535"));
+    assertEquals(0, IPStackUtils.getPort("0"));
   }
 
   @Test
-  void testWildcardWhenHostnameIsProvided() {
-    String result = IPStackUtils.adaptWildcardAddress("example.com");
-    assertEquals("example.com", result);
+  void testGetPortWithInvalidPort() {
+    assertThrows(IllegalArgumentException.class, () -> 
IPStackUtils.getPort("70000"),
+        "Port number out of range (0-65535).");
+    assertThrows(IllegalArgumentException.class, () -> 
IPStackUtils.getPort("-1"),
+        "Port number out of range (0-65535).");
+    assertThrows(IllegalArgumentException.class, () -> 
IPStackUtils.getPort("abc"),
+        "For input string: \"abc\"");
   }
 }
\ No newline at end of file
diff --git a/jdbc/src/java/org/apache/hive/jdbc/ZooKeeperHiveClientHelper.java 
b/jdbc/src/java/org/apache/hive/jdbc/ZooKeeperHiveClientHelper.java
index dfe21e71331..513113bb077 100644
--- a/jdbc/src/java/org/apache/hive/jdbc/ZooKeeperHiveClientHelper.java
+++ b/jdbc/src/java/org/apache/hive/jdbc/ZooKeeperHiveClientHelper.java
@@ -34,6 +34,7 @@
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.hive.common.SSLZookeeperFactory;
 import org.apache.hadoop.hive.conf.HiveConf;
+import org.apache.hive.common.IPStackUtils;
 import org.apache.hive.jdbc.Utils.JdbcConnectionParams;
 import org.apache.hive.service.server.HS2ActivePassiveHARegistry;
 import org.apache.hive.service.server.HS2ActivePassiveHARegistryClient;
@@ -178,12 +179,13 @@ private static void 
updateParamsWithZKServerNode(JdbcConnectionParams connParams
     // it must be the server uri added by an older version HS2
     Matcher matcher = kvPattern.matcher(dataStr);
     if ((dataStr != null) && (!matcher.find())) {
-      String[] split = dataStr.split(":");
-      if (split.length != 2) {
+      try {
+        IPStackUtils.HostPort hostPort = IPStackUtils.getHostAndPort(dataStr);
+        connParams.setHost(hostPort.getHostname());
+        connParams.setPort(hostPort.getPort());
+      } catch (Exception e) {
         throw new ZooKeeperHiveClientException("Unable to parse HiveServer2 
URI from ZooKeeper data: " + dataStr);
       }
-      connParams.setHost(split[0]);
-      connParams.setPort(Integer.parseInt(split[1]));
     } else {
       applyConfs(dataStr, connParams);
     }
diff --git 
a/jdbc/src/test/org/apache/hive/jdbc/ZooKeeperHiveClientHelperTest.java 
b/jdbc/src/test/org/apache/hive/jdbc/ZooKeeperHiveClientHelperTest.java
new file mode 100644
index 00000000000..7b759482efc
--- /dev/null
+++ b/jdbc/src/test/org/apache/hive/jdbc/ZooKeeperHiveClientHelperTest.java
@@ -0,0 +1,120 @@
+/*
+ * 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.jdbc;
+
+import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.framework.api.GetDataBuilder;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.mockito.Mock;
+
+import java.lang.reflect.Method;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.Collection;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@RunWith(Parameterized.class)
+public class ZooKeeperHiveClientHelperTest {
+
+  private Utils.JdbcConnectionParams connParams;
+  private CuratorFramework mockZooKeeperClient;
+
+  @Mock
+  private GetDataBuilder mockGetDataBuilder;
+
+  private final String input;
+  private final String expectedHost;
+  private final int expectedPort;
+  private final boolean expectException;
+
+  public ZooKeeperHiveClientHelperTest(String input, String expectedHost, int 
expectedPort, boolean expectException) {
+    this.input = input;
+    this.expectedHost = expectedHost;
+    this.expectedPort = expectedPort;
+    this.expectException = expectException;
+  }
+
+  @Parameterized.Parameters
+  public static Collection<Object[]> data() {
+    return Arrays.asList(new Object[][]{
+        // Valid cases
+        {"localhost:9090", "localhost", 9090, false},        // Hostname
+        {"192.168.1.1:8080", "192.168.1.1", 8080, false},    // IPv4
+        {"[2001:db8::1]:1234", "2001:db8::1", 1234, false},  // IPv6 with 
square brackets
+        {"2001:db8::1:5678", "2001:db8::1", 5678, false},    // IPv6 without 
square brackets
+
+        // Invalid cases (Invalid host and port format)
+        {"localhost", null, 0, true},         // Missing port
+        {":9090", null, 0, true},             // Missing hostname
+        {"192.168.1.1:", null, 0, true},      // Missing port after IPv4
+        {"[2001:db8::1]", null, 0, true},     // Missing port after IPv6 with 
square brackets
+        {"invalid_host:port", null, 0, true}  // Invalid host
+    });
+  }
+
+  @Before
+  public void setUp() {
+    connParams = new Utils.JdbcConnectionParams();
+    mockZooKeeperClient = mock(CuratorFramework.class);
+    mockGetDataBuilder = mock(GetDataBuilder.class);
+
+    // Mock the getData() method to return mockGetDataBuilder
+    when(mockZooKeeperClient.getData()).thenReturn(mockGetDataBuilder);
+  }
+
+  @Test
+  public void testUpdateParamsWithZKServerNode_HostPortParsing_Success() 
throws Exception {
+    String serverNode = "testServerNode";
+
+    // Mock the behavior of getData().forPath() to return the data bytes
+    
when(mockGetDataBuilder.forPath(anyString())).thenReturn(input.getBytes(StandardCharsets.UTF_8));
+
+    // Access the private method using reflection
+    Method updateParamsMethod = 
ZooKeeperHiveClientHelper.class.getDeclaredMethod(
+        "updateParamsWithZKServerNode", Utils.JdbcConnectionParams.class, 
CuratorFramework.class, String.class);
+
+    // Make the private method accessible
+    updateParamsMethod.setAccessible(true);
+    
+    try {
+      // Call the private method under test
+      updateParamsMethod.invoke(null, connParams, mockZooKeeperClient, 
serverNode);
+
+      if (expectException) {
+        fail("Expected IllegalArgumentException or 
ZooKeeperHiveClientException due to invalid format.");
+      } else {
+        assertEquals(connParams.getHost(), expectedHost);
+        assertEquals(connParams.getPort(), expectedPort);
+      }
+    } catch (Exception e) {
+      // We expect exceptions for invalid input, so the test passes if we 
catch them
+      assertTrue(expectException && 
+          e.getCause() instanceof IllegalArgumentException || e.getCause() 
instanceof ZooKeeperHiveClientException);
+    }
+  }
+}
\ No newline at end of file
diff --git a/ql/src/java/org/apache/hadoop/hive/ql/lockmgr/HiveLockObject.java 
b/ql/src/java/org/apache/hadoop/hive/ql/lockmgr/HiveLockObject.java
index 55ecbb45b9e..197196e0085 100644
--- a/ql/src/java/org/apache/hadoop/hive/ql/lockmgr/HiveLockObject.java
+++ b/ql/src/java/org/apache/hadoop/hive/ql/lockmgr/HiveLockObject.java
@@ -71,20 +71,21 @@ public HiveLockObjectData(String queryId, String lockTime, 
String lockMode, Stri
     /**
      * Constructor
      * 
-     * @param data String of the form "queryId:lockTime:lockMode:queryStr". 
-     * No ':' characters are allowed in any of the components.
+     * @param data String of the form 
"queryId:lockTime:lockMode:queryStr[:clientIp]". 
+     * No ':' characters are allowed in any of the first four components, but 
the clientIp can contain colons (IPv6).
      */
     public HiveLockObjectData(String data) {
       if (data == null) {
         return;
       }
 
-      String[] elem = data.split(":");
+      String[] elem = data.split(":", 5);
       queryId = elem[0];
       lockTime = StringInternUtils.internIfNotNull(elem[1]);
       lockMode = elem[2];
       queryStr = StringInternUtils.internIfNotNull(elem[3]);
       if (elem.length >= 5) {
+        // The client IP is the suffix after the 4th colon, this can be IPv6 
with colons
         clientIp = elem[4];
       }
     }
diff --git 
a/ql/src/test/org/apache/hadoop/hive/ql/lockmgr/TestHiveLockObject.java 
b/ql/src/test/org/apache/hadoop/hive/ql/lockmgr/TestHiveLockObject.java
index 52f86bb0956..3fe1bb4829b 100644
--- a/ql/src/test/org/apache/hadoop/hive/ql/lockmgr/TestHiveLockObject.java
+++ b/ql/src/test/org/apache/hadoop/hive/ql/lockmgr/TestHiveLockObject.java
@@ -18,50 +18,103 @@
 
 package org.apache.hadoop.hive.ql.lockmgr;
 
-import org.junit.Assert;
-
 import org.apache.hadoop.hive.conf.HiveConf;
 import org.apache.hadoop.hive.ql.lockmgr.HiveLockObject.HiveLockObjectData;
 import org.junit.Test;
+import org.junit.experimental.runners.Enclosed;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.util.Arrays;
+import java.util.Collection;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+@RunWith(Enclosed.class)
 public class TestHiveLockObject {
 
-  private HiveConf conf = new HiveConf();
+  public static class TestHiveLockObjectNonParametrized {
+    private final HiveConf conf = new HiveConf();
+
+    @Test
+    public void testEqualsAndHashCode() {
+      HiveLockObjectData data1 = new HiveLockObjectData("ID1", "SHARED", 
"1997-07-01",
+          "select * from mytable", conf);
+      HiveLockObjectData data2 = new HiveLockObjectData("ID1", "SHARED", 
"1997-07-01",
+          "select * from mytable", conf);
+      assertEquals(data1, data2);
+      assertEquals(data1.hashCode(), data2.hashCode());
 
-  @Test
-  public void testEqualsAndHashCode() {
-    HiveLockObjectData data1 = new HiveLockObjectData("ID1", "SHARED", 
"1997-07-01",
-        "select * from mytable", conf);
-    HiveLockObjectData data2 = new HiveLockObjectData("ID1", "SHARED", 
"1997-07-01",
-        "select * from mytable", conf);
-    Assert.assertEquals(data1, data2);
-    Assert.assertEquals(data1.hashCode(), data2.hashCode());
+      HiveLockObject obj1 = new HiveLockObject("mytable", data1);
+      HiveLockObject obj2 = new HiveLockObject("mytable", data2);
+      assertEquals(obj1, obj2);
+      assertEquals(obj1.hashCode(), obj2.hashCode());
+    }
 
-    HiveLockObject obj1 = new HiveLockObject("mytable", data1);
-    HiveLockObject obj2 = new HiveLockObject("mytable", data2);
-    Assert.assertEquals(obj1, obj2);
-    Assert.assertEquals(obj1.hashCode(), obj2.hashCode());
+    @Test
+    public void testTruncate() {
+      conf.setIntVar(HiveConf.ConfVars.HIVE_LOCK_QUERY_STRING_MAX_LENGTH, 
1000000);
+      HiveLockObjectData data0 = new HiveLockObjectData("ID1", "SHARED", 
"1997-07-01",
+          "01234567890", conf);
+      assertEquals("With default settings query string should not be 
truncated",
+          11, data0.getQueryStr().length());
+      conf.setIntVar(HiveConf.ConfVars.HIVE_LOCK_QUERY_STRING_MAX_LENGTH, 10);
+      HiveLockObjectData data1 = new HiveLockObjectData("ID1", "SHARED", 
"1997-07-01",
+          "01234567890", conf);
+      HiveLockObjectData data2 = new HiveLockObjectData("ID1", "SHARED", 
"1997-07-01",
+          "0123456789", conf);
+      HiveLockObjectData data3 = new HiveLockObjectData("ID1", "SHARED", 
"1997-07-01",
+          "012345678", conf);
+      HiveLockObjectData data4 = new HiveLockObjectData("ID1", "SHARED", 
"1997-07-01",
+          null, conf);
+      assertEquals("Long string truncation failed", 10, 
data1.getQueryStr().length());
+      assertEquals("String truncation failed", 10, 
data2.getQueryStr().length());
+      assertEquals("Short string should not be truncated", 9, 
data3.getQueryStr().length());
+      assertNull("Null query string handling failed", data4.getQueryStr());
+    }
   }
 
-  @Test
-  public void testTruncate() {
-    conf.setIntVar(HiveConf.ConfVars.HIVE_LOCK_QUERY_STRING_MAX_LENGTH, 
1000000);
-    HiveLockObjectData data0 = new HiveLockObjectData("ID1", "SHARED", 
"1997-07-01",
-        "01234567890", conf);
-    Assert.assertEquals("With default settings query string should not be 
truncated",
-        data0.getQueryStr().length(), 11);
-    conf.setIntVar(HiveConf.ConfVars.HIVE_LOCK_QUERY_STRING_MAX_LENGTH, 10);
-    HiveLockObjectData data1 = new HiveLockObjectData("ID1", "SHARED", 
"1997-07-01",
-        "01234567890", conf);
-    HiveLockObjectData data2 = new HiveLockObjectData("ID1", "SHARED", 
"1997-07-01",
-        "0123456789", conf);
-    HiveLockObjectData data3 = new HiveLockObjectData("ID1", "SHARED", 
"1997-07-01",
-        "012345678", conf);
-    HiveLockObjectData data4 = new HiveLockObjectData("ID1", "SHARED", 
"1997-07-01",
-        null, conf);
-    Assert.assertEquals("Long string truncation failed", 
data1.getQueryStr().length(), 10);
-    Assert.assertEquals("String truncation failed", 
data2.getQueryStr().length(), 10);
-    Assert.assertEquals("Short string should not be truncated", 
data3.getQueryStr().length(), 9);
-    Assert.assertNull("Null query string handling failed", 
data4.getQueryStr());
+  @RunWith(Parameterized.class)
+  public static class TestHiveLockObjectParametrized {
+
+    private final String data;
+    private final String expectedQueryId;
+    private final String expectedLockTime;
+    private final String expectedLockMode;
+    private final String expectedQueryStr;
+    private final String expectedClientIp;
+
+    public TestHiveLockObjectParametrized(String data, String expectedQueryId, 
String expectedLockTime,
+                              String expectedLockMode, String 
expectedQueryStr, String expectedClientIp) {
+      this.data = data;
+      this.expectedQueryId = expectedQueryId;
+      this.expectedLockTime = expectedLockTime;
+      this.expectedLockMode = expectedLockMode;
+      this.expectedQueryStr = expectedQueryStr;
+      this.expectedClientIp = expectedClientIp;
+    }
+
+    // Method to supply the parameters for the parameterized test
+    @Parameterized.Parameters
+    public static Collection<Object[]> data() {
+      return Arrays.asList(new Object[][] {
+          { "query1:2025-03-31:EXPLICIT:SELECT * FROM table", "query1", 
"2025-03-31", "EXPLICIT", "SELECT * FROM table", null },
+          { "query2:2025-03-31:EXPLICIT:SELECT * FROM table:192.168.0.1", 
"query2", "2025-03-31", "EXPLICIT", "SELECT * FROM table", "192.168.0.1" },
+          { "query3:2025-03-31:EXPLICIT:SELECT * FROM 
table:2001:0db8:85a3:0000:0000:8a2e:0370:7334", "query3", "2025-03-31", 
"EXPLICIT", "SELECT * FROM table", "2001:0db8:85a3:0000:0000:8a2e:0370:7334" },
+          { "query5:2025-03-31:EXPLICIT:SELECT * FROM table:some.company.com", 
"query5", "2025-03-31", "EXPLICIT", "SELECT * FROM table", "some.company.com" }
+      });
+    }
+    
+    @Test
+    public void testConstructor() {
+      HiveLockObjectData lockObjectData = new HiveLockObjectData(data);
+
+      assertEquals("queryId should match", expectedQueryId, 
lockObjectData.getQueryId());
+      assertEquals("lockTime should match", expectedLockTime, 
lockObjectData.getLockTime());
+      assertEquals("lockMode should match", expectedLockMode, 
lockObjectData.getLockMode());
+      assertEquals("queryStr should match", expectedQueryStr, 
lockObjectData.getQueryStr());
+      assertEquals("clientIp should match", expectedClientIp, 
lockObjectData.getClientIp());
+    }
   }
 }
diff --git 
a/service/src/java/org/apache/hive/service/server/HS2ActivePassiveHARegistry.java
 
b/service/src/java/org/apache/hive/service/server/HS2ActivePassiveHARegistry.java
index f7dbe3c4831..bf0f53636ec 100644
--- 
a/service/src/java/org/apache/hive/service/server/HS2ActivePassiveHARegistry.java
+++ 
b/service/src/java/org/apache/hive/service/server/HS2ActivePassiveHARegistry.java
@@ -42,8 +42,8 @@
 import org.apache.hadoop.registry.client.binding.RegistryTypeUtils;
 import org.apache.hadoop.registry.client.types.Endpoint;
 import org.apache.hadoop.registry.client.types.ServiceRecord;
-import org.apache.hadoop.security.UserGroupInformation;
 import org.apache.hadoop.yarn.api.records.ApplicationId;
+import org.apache.hive.common.IPStackUtils;
 import org.apache.hive.service.ServiceException;
 import org.apache.hive.service.auth.AuthType;
 import org.slf4j.Logger;
@@ -173,9 +173,9 @@ private void addEndpointToServiceRecord(
 
   private void updateEndpoint(final ServiceRecord srv, final String 
endpointName) {
     final String instanceUri = srv.get(INSTANCE_URI_CONFIG);
-    final String[] tokens = instanceUri.split(":");
-    final String hostname = tokens[0];
-    final int port = Integer.parseInt(tokens[1]);
+    IPStackUtils.HostPort hostPort = IPStackUtils.getHostAndPort(instanceUri);
+    final String hostname = hostPort.getHostname();
+    final int port = hostPort.getPort();
     Endpoint urlEndpoint = RegistryTypeUtils.ipcEndpoint(endpointName, new 
InetSocketAddress(hostname, port));
     srv.addInternalEndpoint(urlEndpoint);
     LOG.info("Added {} endpoint to service record", urlEndpoint);

Reply via email to