From a3844da10bb3ae788017b4c0699373284d60b058 Mon Sep 17 00:00:00 2001 From: Norman Maurer Date: Fri, 14 Dec 2018 21:31:21 +0100 Subject: [PATCH] NoClassDefFoundError on Android platform when try to use DefaultDnsServerAddressStreamProvider. (#8656) Motivation: Andoid does not contain javax.naming.* so we should not try to use it to prevent a NoClassDefFoundError on init. Modifications: Only try to use javax.naming.* to retrieve nameservers when not using Android. Result: Fixes https://github.com/netty/netty/issues/8654. --- ...DefaultDnsServerAddressStreamProvider.java | 47 ++--------- .../netty/resolver/dns/DirContextUtils.java | 77 +++++++++++++++++++ 2 files changed, 82 insertions(+), 42 deletions(-) create mode 100644 resolver-dns/src/main/java/io/netty/resolver/dns/DirContextUtils.java diff --git a/resolver-dns/src/main/java/io/netty/resolver/dns/DefaultDnsServerAddressStreamProvider.java b/resolver-dns/src/main/java/io/netty/resolver/dns/DefaultDnsServerAddressStreamProvider.java index a5ca38d368..00be072295 100644 --- a/resolver-dns/src/main/java/io/netty/resolver/dns/DefaultDnsServerAddressStreamProvider.java +++ b/resolver-dns/src/main/java/io/netty/resolver/dns/DefaultDnsServerAddressStreamProvider.java @@ -16,23 +16,17 @@ package io.netty.resolver.dns; import io.netty.util.NetUtil; +import io.netty.util.internal.PlatformDependent; import io.netty.util.internal.SocketUtils; import io.netty.util.internal.UnstableApi; import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; -import javax.naming.Context; -import javax.naming.NamingException; -import javax.naming.directory.DirContext; -import javax.naming.directory.InitialDirContext; import java.lang.reflect.Method; import java.net.Inet6Address; import java.net.InetSocketAddress; -import java.net.URI; -import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Collections; -import java.util.Hashtable; import java.util.List; import static io.netty.resolver.dns.DnsServerAddresses.sequential; @@ -55,41 +49,10 @@ public final class DefaultDnsServerAddressStreamProvider implements DnsServerAdd static { final List defaultNameServers = new ArrayList(2); - - // Using jndi-dns to obtain the default name servers. - // - // See: - // - http://docs.oracle.com/javase/8/docs/technotes/guides/jndi/jndi-dns.html - // - http://mail.openjdk.java.net/pipermail/net-dev/2017-March/010695.html - Hashtable env = new Hashtable(); - env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.dns.DnsContextFactory"); - env.put("java.naming.provider.url", "dns://"); - try { - DirContext ctx = new InitialDirContext(env); - String dnsUrls = (String) ctx.getEnvironment().get("java.naming.provider.url"); - // Only try if not empty as otherwise we will produce an exception - if (dnsUrls != null && !dnsUrls.isEmpty()) { - String[] servers = dnsUrls.split(" "); - for (String server : servers) { - try { - URI uri = new URI(server); - String host = new URI(server).getHost(); - - if (host == null || host.isEmpty()) { - logger.debug( - "Skipping a nameserver URI as host portion could not be extracted: {}", server); - // If the host portion can not be parsed we should just skip this entry. - continue; - } - int port = uri.getPort(); - defaultNameServers.add(SocketUtils.socketAddress(uri.getHost(), port == -1 ? DNS_PORT : port)); - } catch (URISyntaxException e) { - logger.debug("Skipping a malformed nameserver URI: {}", server, e); - } - } - } - } catch (NamingException ignore) { - // Will try reflection if this fails. + if (!PlatformDependent.isAndroid()) { + // Only try to use when not on Android as the classes not exists there: + // See https://github.com/netty/netty/issues/8654 + DirContextUtils.addNameServers(defaultNameServers, DNS_PORT); } if (defaultNameServers.isEmpty()) { diff --git a/resolver-dns/src/main/java/io/netty/resolver/dns/DirContextUtils.java b/resolver-dns/src/main/java/io/netty/resolver/dns/DirContextUtils.java new file mode 100644 index 0000000000..45c1ac433f --- /dev/null +++ b/resolver-dns/src/main/java/io/netty/resolver/dns/DirContextUtils.java @@ -0,0 +1,77 @@ +/* + * Copyright 2018 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.resolver.dns; + +import io.netty.util.internal.SocketUtils; +import io.netty.util.internal.logging.InternalLogger; +import io.netty.util.internal.logging.InternalLoggerFactory; + +import javax.naming.Context; +import javax.naming.NamingException; +import javax.naming.directory.DirContext; +import javax.naming.directory.InitialDirContext; +import java.net.InetSocketAddress; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Hashtable; +import java.util.List; + +final class DirContextUtils { + private static final InternalLogger logger = + InternalLoggerFactory.getInstance(DirContextUtils.class); + + private DirContextUtils() { } + + static void addNameServers(List defaultNameServers, int defaultPort) { + // Using jndi-dns to obtain the default name servers. + // + // See: + // - http://docs.oracle.com/javase/8/docs/technotes/guides/jndi/jndi-dns.html + // - http://mail.openjdk.java.net/pipermail/net-dev/2017-March/010695.html + Hashtable env = new Hashtable(); + env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.dns.DnsContextFactory"); + env.put("java.naming.provider.url", "dns://"); + + try { + DirContext ctx = new InitialDirContext(env); + String dnsUrls = (String) ctx.getEnvironment().get("java.naming.provider.url"); + // Only try if not empty as otherwise we will produce an exception + if (dnsUrls != null && !dnsUrls.isEmpty()) { + String[] servers = dnsUrls.split(" "); + for (String server : servers) { + try { + URI uri = new URI(server); + String host = new URI(server).getHost(); + + if (host == null || host.isEmpty()) { + logger.debug( + "Skipping a nameserver URI as host portion could not be extracted: {}", server); + // If the host portion can not be parsed we should just skip this entry. + continue; + } + int port = uri.getPort(); + defaultNameServers.add(SocketUtils.socketAddress(uri.getHost(), port == -1 ? + defaultPort : port)); + } catch (URISyntaxException e) { + logger.debug("Skipping a malformed nameserver URI: {}", server, e); + } + } + } + } catch (NamingException ignore) { + // Will try reflection if this fails. + } + } +}