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.
3839public final class ConnectStringParser {
3940
4041 private static final int DEFAULT_PORT = 2181 ;
42+ private static final String DNS_SRV_PREFIX = "dns-srv://" ;
4143
42- private final String chrootPath ;
44+ public enum ConnectionType {
45+ DNS_SRV ,
46+ HOST_PORT
47+ }
4348
49+ private String chrootPath ;
4450 private final ArrayList <InetSocketAddress > serverAddresses = new ArrayList <>();
51+ private final ConnectionType connectionType ;
52+ private final String connectString ;
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 connect 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 connect string to parse
64+ * @throws IllegalArgumentException if connectString is null/empty or contains invalid chroot path
5165 */
52- public ConnectStringParser (String connectString ) {
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+ if (connectString .startsWith (DNS_SRV_PREFIX )) {
72+ connectionType = ConnectionType .DNS_SRV ;
73+ parseDnsSrvFormat (connectString );
74+ } else {
75+ connectionType = ConnectionType .HOST_PORT ;
76+ parseHostPortFormat (connectString );
77+ }
78+ this .connectString = connectString ;
79+ }
80+
81+ public String getChrootPath () {
82+ return chrootPath ;
83+ }
84+
85+ public ArrayList <InetSocketAddress > getServerAddresses () {
86+ return serverAddresses ;
87+ }
88+
89+ public ConnectionType getConnectionType () {
90+ return connectionType ;
91+ }
92+
93+ public String getConnectString () {
94+ return connectString ;
95+ }
96+
97+ private String [] parseConnectString (final String connectString ) {
98+ String serverPart = connectString ;
99+ String chrootPath = null ;
100+
53101 // parse out chroot, if any
54- int off = connectString .indexOf ('/' );
102+ final int off = connectString .indexOf ('/' );
55103 if (off >= 0 ) {
56- String chrootPath = connectString .substring (off );
104+ chrootPath = connectString .substring (off );
57105 // ignore "/" chroot spec, same as null
58106 if (chrootPath .length () == 1 ) {
59- this . chrootPath = null ;
107+ chrootPath = null ;
60108 } else {
61109 PathUtils .validatePath (chrootPath );
62- this .chrootPath = chrootPath ;
63110 }
64- connectString = connectString .substring (0 , off );
65- } else {
66- this .chrootPath = null ;
111+ serverPart = connectString .substring (0 , off );
67112 }
113+ return new String []{serverPart , chrootPath };
114+ }
115+
116+ private void parseHostPortFormat (final String connectString ) {
117+ final String [] parts = parseConnectString (connectString );
118+ chrootPath = parts [1 ];
68119
69- List <String > hostsList = split (connectString , "," );
120+ final List <String > hostsList = split (parts [ 0 ] , "," );
70121 for (String host : hostsList ) {
71122 int port = DEFAULT_PORT ;
72- String [] hostAndPort = NetUtils .getIPV6HostAndPort (host );
123+ final String [] hostAndPort = NetUtils .getIPV6HostAndPort (host );
73124 if (hostAndPort .length != 0 ) {
74125 host = hostAndPort [0 ];
75126 if (hostAndPort .length == 2 ) {
@@ -89,12 +140,11 @@ public ConnectStringParser(String connectString) {
89140 }
90141 }
91142
92- public String getChrootPath () {
93- return chrootPath ;
143+ private void parseDnsSrvFormat (final String connectString ) {
144+ final String [] parts = parseConnectString (connectString .substring (DNS_SRV_PREFIX .length ()));
145+ chrootPath = parts [1 ];
146+ // The DNS service name is stored as a placeholder address
147+ // The actual resolution will be handled by DnsSrvHostProvider
148+ serverAddresses .add (InetSocketAddress .createUnresolved (parts [0 ], DEFAULT_PORT ));
94149 }
95-
96- public ArrayList <InetSocketAddress > getServerAddresses () {
97- return serverAddresses ;
98- }
99-
100150}
0 commit comments