Motivation Applications should not depend on internal packages with Java 9 and later. This cause a warning now, but will break in future versions of Java. Modification This change adds methods to UnixResolverDnsServerAddressStreamProvider (following after #6844) that parse /etc/resolv.conf for domain and search entries. Then DnsNameResolver does not need to rely on sun.net.dns.ResolverConfiguration to do this. Result Fixes #8318. Furthermore, at least in my testing with Java 11, this also makes multiple search entries work properly (previously I was only getting the first entry).
This commit is contained in:
parent
618a98fdb5
commit
ba594bcf4a
@ -125,13 +125,9 @@ public class DnsNameResolver extends InetNameResolver {
|
||||
static {
|
||||
String[] searchDomains;
|
||||
try {
|
||||
Class<?> configClass = Class.forName("sun.net.dns.ResolverConfiguration");
|
||||
Method open = configClass.getMethod("open");
|
||||
Method nameservers = configClass.getMethod("searchlist");
|
||||
Object instance = open.invoke(null);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
List<String> list = (List<String>) nameservers.invoke(instance);
|
||||
List<String> list = PlatformDependent.isWindows()
|
||||
? getSearchDomainsHack()
|
||||
: UnixResolverDnsServerAddressStreamProvider.parseEtcResolverSearchDomains();
|
||||
searchDomains = list.toArray(new String[0]);
|
||||
} catch (Exception ignore) {
|
||||
// Failed to get the system name search domain list.
|
||||
@ -148,6 +144,18 @@ public class DnsNameResolver extends InetNameResolver {
|
||||
DEFAULT_NDOTS = ndots;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static List<String> getSearchDomainsHack() throws Exception {
|
||||
// This code on Java 9+ yields a warning about illegal reflective access that will be denied in
|
||||
// a future release. There doesn't seem to be a better way to get search domains for Windows yet.
|
||||
Class<?> configClass = Class.forName("sun.net.dns.ResolverConfiguration");
|
||||
Method open = configClass.getMethod("open");
|
||||
Method nameservers = configClass.getMethod("searchlist");
|
||||
Object instance = open.invoke(null);
|
||||
|
||||
return (List<String>) nameservers.invoke(instance);
|
||||
}
|
||||
|
||||
private static final DatagramDnsResponseDecoder DECODER = new DatagramDnsResponseDecoder();
|
||||
private static final DatagramDnsQueryEncoder ENCODER = new DatagramDnsQueryEncoder();
|
||||
|
||||
|
@ -27,7 +27,9 @@ import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -51,6 +53,7 @@ public final class UnixResolverDnsServerAddressStreamProvider implements DnsServ
|
||||
private static final String SORTLIST_ROW_LABEL = "sortlist";
|
||||
private static final String OPTIONS_ROW_LABEL = "options";
|
||||
private static final String DOMAIN_ROW_LABEL = "domain";
|
||||
private static final String SEARCH_ROW_LABEL = "search";
|
||||
private static final String PORT_ROW_LABEL = "port";
|
||||
private static final String NDOTS_LABEL = "ndots:";
|
||||
static final int DEFAULT_NDOTS = 1;
|
||||
@ -284,4 +287,57 @@ public final class UnixResolverDnsServerAddressStreamProvider implements DnsServ
|
||||
}
|
||||
return DEFAULT_NDOTS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a file of the format <a href="https://linux.die.net/man/5/resolver">/etc/resolv.conf</a> and return the
|
||||
* list of search domains found in it or an empty list if not found.
|
||||
* @return List of search domains.
|
||||
* @throws IOException If a failure occurs parsing the file.
|
||||
*/
|
||||
static List<String> parseEtcResolverSearchDomains() throws IOException {
|
||||
return parseEtcResolverSearchDomains(new File(ETC_RESOLV_CONF_FILE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a file of the format <a href="https://linux.die.net/man/5/resolver">/etc/resolv.conf</a> and return the
|
||||
* list of search domains found in it or an empty list if not found.
|
||||
* @param etcResolvConf a file of the format <a href="https://linux.die.net/man/5/resolver">/etc/resolv.conf</a>.
|
||||
* @return List of search domains.
|
||||
* @throws IOException If a failure occurs parsing the file.
|
||||
*/
|
||||
static List<String> parseEtcResolverSearchDomains(File etcResolvConf) throws IOException {
|
||||
String localDomain = null;
|
||||
List<String> searchDomains = new ArrayList<String>();
|
||||
|
||||
FileReader fr = new FileReader(etcResolvConf);
|
||||
BufferedReader br = null;
|
||||
try {
|
||||
br = new BufferedReader(fr);
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
if (localDomain == null && line.startsWith(DOMAIN_ROW_LABEL)) {
|
||||
int i = indexOfNonWhiteSpace(line, DOMAIN_ROW_LABEL.length());
|
||||
if (i >= 0) {
|
||||
localDomain = line.substring(i);
|
||||
}
|
||||
} else if (line.startsWith(SEARCH_ROW_LABEL)) {
|
||||
int i = indexOfNonWhiteSpace(line, SEARCH_ROW_LABEL.length());
|
||||
if (i >= 0) {
|
||||
searchDomains.add(line.substring(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (br == null) {
|
||||
fr.close();
|
||||
} else {
|
||||
br.close();
|
||||
}
|
||||
}
|
||||
|
||||
// return what was on the 'domain' line only if there were no 'search' lines
|
||||
return localDomain != null && searchDomains.isEmpty()
|
||||
? Collections.singletonList(localDomain)
|
||||
: searchDomains;
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,9 @@ import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static io.netty.resolver.dns.UnixResolverDnsServerAddressStreamProvider.DEFAULT_NDOTS;
|
||||
import static io.netty.resolver.dns.UnixResolverDnsServerAddressStreamProvider.parseEtcResolverFirstNdots;
|
||||
@ -111,6 +114,40 @@ public class UnixResolverDnsServerAddressStreamProviderTest {
|
||||
assertHostNameEquals("127.0.0.2", stream.next());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void searchDomainsWithOnlyDomain() throws IOException {
|
||||
File f = buildFile("domain linecorp.local\n" +
|
||||
"nameserver 127.0.0.2\n");
|
||||
List<String> domains = UnixResolverDnsServerAddressStreamProvider.parseEtcResolverSearchDomains(f);
|
||||
assertEquals(Collections.singletonList("linecorp.local"), domains);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void searchDomainsWithOnlySearch() throws IOException {
|
||||
File f = buildFile("search linecorp.local\n" +
|
||||
"nameserver 127.0.0.2\n");
|
||||
List<String> domains = UnixResolverDnsServerAddressStreamProvider.parseEtcResolverSearchDomains(f);
|
||||
assertEquals(Collections.singletonList("linecorp.local"), domains);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void searchDomainsWithMultipleSearch() throws IOException {
|
||||
File f = buildFile("search linecorp.local\n" +
|
||||
"search squarecorp.local\n" +
|
||||
"nameserver 127.0.0.2\n");
|
||||
List<String> domains = UnixResolverDnsServerAddressStreamProvider.parseEtcResolverSearchDomains(f);
|
||||
assertEquals(Arrays.asList("linecorp.local", "squarecorp.local"), domains);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void searchDomainsPrecedence() throws IOException {
|
||||
File f = buildFile("domain linecorp.local\n" +
|
||||
"search squarecorp.local\n" +
|
||||
"nameserver 127.0.0.2\n");
|
||||
List<String> domains = UnixResolverDnsServerAddressStreamProvider.parseEtcResolverSearchDomains(f);
|
||||
assertEquals(Collections.singletonList("squarecorp.local"), domains);
|
||||
}
|
||||
|
||||
private File buildFile(String contents) throws IOException {
|
||||
File f = folder.newFile();
|
||||
OutputStream out = new FileOutputStream(f);
|
||||
|
Loading…
Reference in New Issue
Block a user