16
16
17
17
package com .mongodb .internal .dns ;
18
18
19
- import com .mongodb .MongoClientException ;
20
19
import com .mongodb .MongoConfigurationException ;
20
+ import com .mongodb .spi .dns .DnsClient ;
21
+ import com .mongodb .spi .dns .DnsClientProvider ;
22
+ import com .mongodb .spi .dns .DnsWithResponseCodeException ;
21
23
22
- import javax .naming .Context ;
23
- import javax .naming .NameNotFoundException ;
24
- import javax .naming .NamingEnumeration ;
25
- import javax .naming .NamingException ;
26
- import javax .naming .directory .Attribute ;
27
- import javax .naming .directory .Attributes ;
28
- import javax .naming .directory .InitialDirContext ;
29
24
import java .util .ArrayList ;
30
- import java .util .Hashtable ;
31
25
import java .util .List ;
26
+ import java .util .ServiceLoader ;
32
27
33
28
import static java .lang .String .format ;
34
29
import static java .util .Arrays .asList ;
40
35
*/
41
36
public final class DefaultDnsResolver implements DnsResolver {
42
37
38
+ private final DnsClient dnsClient ;
39
+
40
+ public DefaultDnsResolver () {
41
+ ServiceLoader <DnsClientProvider > loader = ServiceLoader .load (DnsClientProvider .class );
42
+ DnsClient dnsClientFromServiceLoader = null ;
43
+ for (DnsClientProvider dnsClientProvider : loader ) {
44
+ dnsClientFromServiceLoader = dnsClientProvider .create ();
45
+ break ;
46
+ }
47
+
48
+ if (dnsClientFromServiceLoader == null ) {
49
+ dnsClient = new JndiDnsClient ();
50
+ } else {
51
+ dnsClient = dnsClientFromServiceLoader ;
52
+ }
53
+ }
54
+
43
55
/*
44
56
The format of SRV record is
45
57
priority weight port target.
@@ -56,40 +68,28 @@ The priority and weight are ignored, and we just concatenate the host (after rem
56
68
public List <String > resolveHostFromSrvRecords (final String srvHost , final String srvServiceName ) {
57
69
String srvHostDomain = srvHost .substring (srvHost .indexOf ('.' ) + 1 );
58
70
List <String > srvHostDomainParts = asList (srvHostDomain .split ("\\ ." ));
59
- List <String > hosts = new ArrayList <String >();
60
- InitialDirContext dirContext = createDnsDirContext () ;
71
+ List <String > hosts = new ArrayList <>();
72
+ String resourceName = "_" + srvServiceName + "._tcp." + srvHost ;
61
73
try {
62
- String resourceRecordName = "_" + srvServiceName + "._tcp." + srvHost ;
63
- Attributes attributes = dirContext .getAttributes (resourceRecordName , new String []{"SRV" });
64
- Attribute attribute = attributes .get ("SRV" );
65
- if (attribute == null ) {
66
- throw new MongoConfigurationException (format ("No SRV records available for %s" , resourceRecordName ));
74
+ List <String > srvAttributeValues = dnsClient .getResourceRecordData (resourceName , "SRV" );
75
+ if (srvAttributeValues == null || srvAttributeValues .isEmpty ()) {
76
+ throw new MongoConfigurationException (format ("No SRV records available for '%s'." , resourceName ));
67
77
}
68
- NamingEnumeration <?> srvRecordEnumeration = attribute .getAll ();
69
- while (srvRecordEnumeration .hasMore ()) {
70
- String srvRecord = (String ) srvRecordEnumeration .next ();
78
+
79
+ for (String srvRecord : srvAttributeValues ) {
71
80
String [] split = srvRecord .split (" " );
72
81
String resolvedHost = split [3 ].endsWith ("." ) ? split [3 ].substring (0 , split [3 ].length () - 1 ) : split [3 ];
73
82
String resolvedHostDomain = resolvedHost .substring (resolvedHost .indexOf ('.' ) + 1 );
74
83
if (!sameParentDomain (srvHostDomainParts , resolvedHostDomain )) {
75
84
throw new MongoConfigurationException (
76
- format ("The SRV host name '%s'resolved to a host '%s 'that is not in a sub-domain of the SRV host." ,
85
+ format ("The SRV host name '%s' resolved to a host '%s 'that is not in a sub-domain of the SRV host." ,
77
86
srvHost , resolvedHost ));
78
87
}
79
88
hosts .add (resolvedHost + ":" + split [2 ]);
80
89
}
81
90
82
- if (hosts .isEmpty ()) {
83
- throw new MongoConfigurationException ("Unable to find any SRV records for host " + srvHost );
84
- }
85
- } catch (NamingException e ) {
86
- throw new MongoConfigurationException ("Unable to look up SRV record for host " + srvHost , e );
87
- } finally {
88
- try {
89
- dirContext .close ();
90
- } catch (NamingException e ) {
91
- // ignore
92
- }
91
+ } catch (Exception e ) {
92
+ throw new MongoConfigurationException (format ("Failed looking up SRV record for '%s'." , resourceName ), e );
93
93
}
94
94
return hosts ;
95
95
}
@@ -110,58 +110,27 @@ private static boolean sameParentDomain(final List<String> srvHostDomainParts, f
110
110
*/
111
111
@ Override
112
112
public String resolveAdditionalQueryParametersFromTxtRecords (final String host ) {
113
- String additionalQueryParameters = "" ;
114
- InitialDirContext dirContext = createDnsDirContext ();
115
113
try {
116
- Attributes attributes = dirContext .getAttributes (host , new String []{"TXT" });
117
- Attribute attribute = attributes .get ("TXT" );
118
- if (attribute != null ) {
119
- NamingEnumeration <?> txtRecordEnumeration = attribute .getAll ();
120
- if (txtRecordEnumeration .hasMore ()) {
121
- // Remove all space characters, as the DNS resolver for TXT records inserts a space character
122
- // between each character-string in a single TXT record. That whitespace is spurious in
123
- // this context and must be removed
124
- additionalQueryParameters = ((String ) txtRecordEnumeration .next ()).replaceAll ("\\ s" , "" );
125
-
126
- if (txtRecordEnumeration .hasMore ()) {
127
- throw new MongoConfigurationException (format ("Multiple TXT records found for host '%s'. Only one is permitted" ,
128
- host ));
129
- }
130
- }
114
+ List <String > attributeValues = dnsClient .getResourceRecordData (host , "TXT" );
115
+ if (attributeValues == null || attributeValues .isEmpty ()) {
116
+ return "" ;
131
117
}
132
- } catch (NameNotFoundException e ) {
133
- // ignore NXDomain error (error code 3, "Non-Existent Domain)
134
- } catch (NamingException e ) {
135
- throw new MongoConfigurationException ("Unable to look up TXT record for host " + host , e );
136
- } finally {
137
- try {
138
- dirContext .close ();
139
- } catch (NamingException e ) {
140
- // ignore
118
+ if (attributeValues .size () > 1 ) {
119
+ throw new MongoConfigurationException (format ("Multiple TXT records found for host '%s'. Only one is permitted" ,
120
+ host ));
141
121
}
142
- }
143
- return additionalQueryParameters ;
144
- }
145
-
146
- /*
147
- It's unfortunate that we take a runtime dependency on com.sun.jndi.dns.DnsContextFactory.
148
- This is not guaranteed to work on all JVMs but in practice is expected to work on most.
149
- */
150
- private static InitialDirContext createDnsDirContext () {
151
- Hashtable <String , String > envProps = new Hashtable <String , String >();
152
- envProps .put (Context .INITIAL_CONTEXT_FACTORY , "com.sun.jndi.dns.DnsContextFactory" );
153
-
154
- try {
155
- return new InitialDirContext (envProps );
156
- } catch (NamingException e ) {
157
- // Just in case the provider url default has been changed to a non-dns pseudo url, fallback to the JDK default
158
- envProps .put (Context .PROVIDER_URL , "dns:" );
159
- try {
160
- return new InitialDirContext (envProps );
161
- } catch (NamingException ex ) {
162
- throw new MongoClientException ("Unable to support mongodb+srv// style connections as the 'com.sun.jndi.dns.DnsContextFactory' "
163
- + "class is not available in this JRE. A JNDI context is required for resolving SRV records." , e );
122
+ // Remove all space characters, as the DNS resolver for TXT records inserts a space character
123
+ // between each character-string in a single TXT record. That whitespace is spurious in
124
+ // this context and must be removed
125
+ return attributeValues .get (0 ).replaceAll ("\\ s" , "" );
126
+ } catch (DnsWithResponseCodeException e ) {
127
+ // ignore NXDomain error (error code 3, "Non-Existent Domain)
128
+ if (e .getResponseCode () != 3 ) {
129
+ throw new MongoConfigurationException ("Failed looking up TXT record for host " + host , e );
164
130
}
131
+ return "" ;
132
+ } catch (Exception e ) {
133
+ throw new MongoConfigurationException ("Failed looking up TXT record for host " + host , e );
165
134
}
166
135
}
167
136
}
0 commit comments