2424import java .util .List ;
2525import org .apache .zookeeper .common .NetUtils ;
2626import org .apache .zookeeper .common .PathUtils ;
27+ import org .apache .zookeeper .common .StringUtils ;
2728
2829/**
2930 * A parser for ZooKeeper Client connect strings.
3738 */
3839public final class ConnectStringParser {
3940
40- private static final int DEFAULT_PORT = 2181 ;
41+ public enum ConnectionType {
42+ DNS_SRV ,
43+ HOST_PORT
44+ }
4145
42- private final String chrootPath ;
46+ private static final String DNS_SRV_PREFIX = "dns-srv://" ;
47+ private static final int DEFAULT_PORT = 2181 ;
4348
49+ private final String connectString ;
50+ private final ConnectionType connectionType ;
51+ private String chrootPath ;
4452 private final ArrayList <InetSocketAddress > serverAddresses = new ArrayList <>();
4553
4654 /**
47- * Parse host and port by splitting client connectString
48- * with support for IPv6 literals
49- * @throws IllegalArgumentException
50- * for an invalid chroot path.
55+ * Constructs a ConnectStringParser with given connection string.
56+ *
57+ * <p>Supports two connection string formats:</p>
58+ * <ul>
59+ * <li><strong>Host:Port format:</strong> "host1:2181,host2:2181/chroot"</li>
60+ * <li><strong>DNS SRV format:</strong> "dns-srv://service.domain.com/chroot"</li>
61+ * </ul>
62+ *
63+ * @param connectString the connection string to parse
64+ * @throws IllegalArgumentException if connectString is null/empty or contains invalid chroot path
5165 */
52- public ConnectStringParser (String connectString ) {
53- // parse out chroot, if any
54- int off = connectString .indexOf ('/' );
55- if (off >= 0 ) {
56- String chrootPath = connectString .substring (off );
57- // ignore "/" chroot spec, same as null
58- if (chrootPath .length () == 1 ) {
59- this .chrootPath = null ;
60- } else {
61- PathUtils .validatePath (chrootPath );
62- this .chrootPath = chrootPath ;
63- }
64- connectString = connectString .substring (0 , off );
66+ public ConnectStringParser (final String connectString ) {
67+ if (StringUtils .isBlank (connectString )) {
68+ throw new IllegalArgumentException ("Connect string cannot be null or empty" );
69+ }
70+
71+ this .connectString = connectString ;
72+ if (connectString .startsWith (DNS_SRV_PREFIX )) {
73+ connectionType = ConnectionType .DNS_SRV ;
74+ parseDnsSrvFormat (connectString );
6575 } else {
66- this .chrootPath = null ;
76+ connectionType = ConnectionType .HOST_PORT ;
77+ parseHostPortFormat (connectString );
6778 }
79+ }
80+
81+ public String getChrootPath () {
82+ return chrootPath ;
83+ }
84+
85+ public ArrayList <InetSocketAddress > getServerAddresses () {
86+ return serverAddresses ;
87+ }
6888
69- List <String > hostsList = split (connectString , "," );
89+ public String getConnectString () {
90+ return connectString ;
91+ }
92+
93+ public ConnectionType getConnectionType () {
94+ return connectionType ;
95+ }
96+
97+ private void parseDnsSrvFormat (final String connectString ) {
98+ final String dnsName = connectString .substring (DNS_SRV_PREFIX .length ());
99+ final String [] parts = extractChrootPath (dnsName );
100+ final String dnsServiceName = parts [0 ];
101+
102+ chrootPath = parts [1 ];
103+ // The DNS service name is stored as a placeholder address
104+ // The actual resolution will be handled by DnsSrvHostProvider
105+ serverAddresses .add (InetSocketAddress .createUnresolved (dnsServiceName , DEFAULT_PORT ));
106+ }
107+
108+ private void parseHostPortFormat (String connectString ) {
109+ final String [] parts = extractChrootPath (connectString );
110+ final String serverPart = parts [0 ];
111+ chrootPath = parts [1 ];
112+
113+ final List <String > hostsList = split (serverPart , "," );
70114 for (String host : hostsList ) {
71115 int port = DEFAULT_PORT ;
72- String [] hostAndPort = NetUtils .getIPV6HostAndPort (host );
116+ final String [] hostAndPort = NetUtils .getIPV6HostAndPort (host );
73117 if (hostAndPort .length != 0 ) {
74118 host = hostAndPort [0 ];
75119 if (hostAndPort .length == 2 ) {
@@ -89,12 +133,23 @@ public ConnectStringParser(String connectString) {
89133 }
90134 }
91135
92- public String getChrootPath ( ) {
93- return chrootPath ;
94- }
136+ private String [] extractChrootPath ( final String connectionString ) {
137+ String serverPart = connectionString ;
138+ String chrootPath = null ;
95139
96- public ArrayList <InetSocketAddress > getServerAddresses () {
97- return serverAddresses ;
140+ // parse out chroot, if any
141+ final int chrootIndex = connectionString .indexOf ('/' );
142+ if (chrootIndex >= 0 ) {
143+ chrootPath = connectionString .substring (chrootIndex );
144+ // ignore "/" chroot spec, same as null
145+ if (chrootPath .length () == 1 ) {
146+ chrootPath = null ;
147+ } else {
148+ PathUtils .validatePath (chrootPath );
149+ }
150+ serverPart = connectionString .substring (0 , chrootIndex );
151+ }
152+ return new String []{serverPart , chrootPath };
98153 }
99154
100155}
0 commit comments