|
18 | 18 | package org.apache.hadoop.hbase;
|
19 | 19 |
|
20 | 20 | import java.io.Serializable;
|
| 21 | +import java.io.UnsupportedEncodingException; |
| 22 | +import java.net.URLDecoder; |
| 23 | +import java.net.URLEncoder; |
21 | 24 | import java.util.ArrayList;
|
22 | 25 | import java.util.Iterator;
|
23 | 26 | import java.util.List;
|
@@ -62,6 +65,12 @@ public class ServerName implements Comparable<ServerName>, Serializable {
|
62 | 65 | */
|
63 | 66 | private static final short VERSION = 0;
|
64 | 67 | static final byte[] VERSION_BYTES = Bytes.toBytes(VERSION);
|
| 68 | + private static final String COLON_ENCODED_VALUE = "%3a"; |
| 69 | + |
| 70 | + public static final String COLON = ":"; |
| 71 | + |
| 72 | + // IPV6 address length separated by COLON(:), eg: "0:0:0:0:0:0:0:1".split(colon).length |
| 73 | + private static final int IPV6_SPLIT_COLON_LENGTH = 8; |
65 | 74 |
|
66 | 75 | /**
|
67 | 76 | * What to use if no startcode supplied.
|
@@ -424,7 +433,49 @@ public static ServerName parseVersionedServerName(final byte[] versionedBytes) {
|
424 | 433 | * @return A ServerName instance.
|
425 | 434 | */
|
426 | 435 | public static ServerName parseServerName(final String str) {
|
427 |
| - return SERVERNAME_PATTERN.matcher(str).matches() ? valueOf(str) : valueOf(str, NON_STARTCODE); |
| 436 | + ServerName sn = |
| 437 | + SERVERNAME_PATTERN.matcher(str).matches() ? valueOf(str) : valueOf(str, NON_STARTCODE); |
| 438 | + String hostname = sn.getHostname(); |
| 439 | + // if IPV6 address is in encoded format, need to check and validate its address length |
| 440 | + // eg: if address is like "0%3a0%3a0%3a0%3a0%3a0%3a0%3a0%3a1,16020,1720673488765" decode to |
| 441 | + // "0:0:0:0:0:0:0:1,16020,1720673488765" |
| 442 | + if (isIpv6ServerName(hostname, COLON_ENCODED_VALUE)) { |
| 443 | + try { |
| 444 | + hostname = URLDecoder.decode(sn.getHostname(), "UTF8"); |
| 445 | + return ServerName.valueOf(hostname, sn.getPort(), sn.getStartCode()); |
| 446 | + } catch (UnsupportedEncodingException e) { |
| 447 | + throw new IllegalArgumentException("Exception occurred while decoding server name", e); |
| 448 | + } |
| 449 | + } |
| 450 | + return sn; |
| 451 | + } |
| 452 | + |
| 453 | + /** |
| 454 | + * Verify the ServerAddress is in IPV6 format or not |
| 455 | + * @param serverAddress IP address |
| 456 | + * @param addressSeparator IPV6 address separator |
| 457 | + * @return true if server address is in IPV6 format |
| 458 | + */ |
| 459 | + public static boolean isIpv6ServerName(String serverAddress, String addressSeparator) { |
| 460 | + return serverAddress.contains(addressSeparator) |
| 461 | + && serverAddress.split(addressSeparator).length == IPV6_SPLIT_COLON_LENGTH; |
| 462 | + } |
| 463 | + |
| 464 | + /** |
| 465 | + * Encode the Server Address |
| 466 | + * @param str Either an instance of {@link #toString()} or a "'<hostname>' ':' |
| 467 | + * '<port>'". |
| 468 | + * @return ServerName instance |
| 469 | + */ |
| 470 | + public static ServerName getEncodedServerName(final String str) { |
| 471 | + ServerName sn = |
| 472 | + SERVERNAME_PATTERN.matcher(str).matches() ? valueOf(str) : valueOf(str, NON_STARTCODE); |
| 473 | + try { |
| 474 | + return ServerName.valueOf(URLEncoder.encode(sn.getHostname(), "UTF8"), sn.getPort(), |
| 475 | + sn.getStartCode()); |
| 476 | + } catch (UnsupportedEncodingException e) { |
| 477 | + throw new IllegalArgumentException("Exception occurred while encoding server name", e); |
| 478 | + } |
428 | 479 | }
|
429 | 480 |
|
430 | 481 | /** Returns true if the String follows the pattern of {@link #toString()}, false otherwise. */
|
|
0 commit comments