Path: blob/master/src/java.base/windows/classes/sun/net/dns/ResolverConfigurationImpl.java
41139 views
/*1* Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.net.dns;2627import java.util.ArrayList;28import java.util.List;29import java.util.concurrent.TimeUnit;3031/*32* An implementation of sun.net.ResolverConfiguration for Windows.33*/3435public class ResolverConfigurationImpl36extends ResolverConfiguration37{38// Lock held whilst loading configuration or checking39private static Object lock = new Object();4041// Resolver options42private final Options opts;4344// Addresses have changed. We default to true to make sure we45// resolve the first time it is requested.46private static boolean changed = true;4748// Time of last refresh.49private static long lastRefresh;5051// Cache timeout (120 seconds) - should be converted into property52// or configured as preference in the future.53private static final long TIMEOUT_NANOS = TimeUnit.SECONDS.toNanos(120);5455// DNS suffix list and name servers populated by native method56private static String os_searchlist;57private static String os_nameservers;5859// Cached lists60private static ArrayList<String> searchlist;61private static ArrayList<String> nameservers;6263// Parse string that consists of token delimited by comma64// and return ArrayList. Refer to ResolverConfigurationImpl.c and65// strappend to see how the string is created.66private ArrayList<String> stringToList(String str) {67// String is delimited by comma.68String[] tokens = str.split(",");69ArrayList<String> l = new ArrayList<>(tokens.length);70for (String s : tokens) {71if (!s.isEmpty() && !l.contains(s)) {72l.add(s);73}74}75l.trimToSize();76return l;77}7879// Parse string that consists of token delimited by comma80// and return ArrayList. Refer to ResolverConfigurationImpl.c and81// strappend to see how the string is created.82// In addition to splitting the string, converts IPv6 addresses to83// BSD-style.84private ArrayList<String> addressesToList(String str) {85// String is delimited by comma86String[] tokens = str.split(",");87ArrayList<String> l = new ArrayList<>(tokens.length);8889for (String s : tokens) {90if (!s.isEmpty()) {91if (s.indexOf(':') >= 0 && s.charAt(0) != '[') {92// Not BSD style93s = '[' + s + ']';94}95if (!s.isEmpty() && !l.contains(s)) {96l.add(s);97}98}99}100l.trimToSize();101return l;102}103104// Load DNS configuration from OS105106private void loadConfig() {107assert Thread.holdsLock(lock);108109// A change in the network address of the machine usually indicates110// a change in DNS configuration too so we always refresh the config111// after such a change.112if (changed) {113changed = false;114} else {115// Otherwise we refresh if TIMEOUT_NANOS has passed since last116// load.117long currTime = System.nanoTime();118// lastRefresh will always have been set once because we start with119// changed = true.120if ((currTime - lastRefresh) < TIMEOUT_NANOS) {121return;122}123}124125// Native code that uses Windows API to find out the DNS server126// addresses and search suffixes. It builds a comma-delimited string127// of nameservers and domain suffixes and sets them to the static128// os_nameservers and os_searchlist. We then split these into Java129// Lists here.130loadDNSconfig0();131132// Record the time of update and refresh the lists of addresses /133// domain suffixes.134lastRefresh = System.nanoTime();135searchlist = stringToList(os_searchlist);136nameservers = addressesToList(os_nameservers);137os_searchlist = null; // can be GC'ed138os_nameservers = null;139}140141ResolverConfigurationImpl() {142opts = new OptionsImpl();143}144145@SuppressWarnings("unchecked") // clone()146public List<String> searchlist() {147synchronized (lock) {148loadConfig();149150// List is mutable so return a shallow copy151return (List<String>)searchlist.clone();152}153}154155@SuppressWarnings("unchecked") // clone()156public List<String> nameservers() {157synchronized (lock) {158loadConfig();159160// List is mutable so return a shallow copy161return (List<String>)nameservers.clone();162}163}164165public Options options() {166return opts;167}168169// --- Address Change Listener170171static class AddressChangeListener extends Thread {172public void run() {173for (;;) {174// wait for configuration to change175if (notifyAddrChange0() != 0)176return;177synchronized (lock) {178changed = true;179}180}181}182}183184185// --- Native methods --186187static native void init0();188189static native void loadDNSconfig0();190191static native int notifyAddrChange0();192193static {194jdk.internal.loader.BootLoader.loadLibrary("net");195init0();196197// start the address listener thread198AddressChangeListener thr = new AddressChangeListener();199thr.setDaemon(true);200thr.start();201}202}203204/**205* Implementation of {@link ResolverConfiguration.Options}206*/207class OptionsImpl extends ResolverConfiguration.Options {208}209210211