src/jdk.dns.client/windows/classes/jdk/dns/conf/DnsResolverConfiguration.java
branchaefimov-dns-client-branch
changeset 58870 35c438a6d45c
child 59100 b92aac38b046
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.dns.client/windows/classes/jdk/dns/conf/DnsResolverConfiguration.java	Thu Oct 31 16:16:21 2019 +0000
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.dns.conf;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.StringTokenizer;
+
+public class DnsResolverConfiguration {
+    // Lock held whilst loading configuration or checking
+    private static ReentrantLock lock = new ReentrantLock();
+
+    // Addresses have changed
+    private static boolean changed = false;
+
+    // Time of last refresh.
+    private static long lastRefresh = -1;
+
+    // Cache timeout (120 seconds) - should be converted into property
+    // or configured as preference in the future.
+    private static final int TIMEOUT = 120000;
+
+    // DNS suffix list and name servers populated by native method
+    private static String os_searchlist;
+    private static String os_nameservers;
+
+    // Cached lists
+    private static LinkedList<String> searchlist;
+    private static LinkedList<String> nameservers;
+
+    // Parse string that consists of token delimited by space or commas
+    // and return LinkedHashMap
+    private LinkedList<String> stringToList(String str) {
+        LinkedList<String> ll = new LinkedList<>();
+
+        // comma and space are valid delimiters
+        StringTokenizer st = new StringTokenizer(str, ", ");
+        while (st.hasMoreTokens()) {
+            String s = st.nextToken();
+            if (!ll.contains(s)) {
+                ll.add(s);
+            }
+        }
+        return ll;
+    }
+
+    // Load DNS configuration from OS
+
+    private void loadConfig() {
+        assert lock.isHeldByCurrentThread();
+
+        // if address have changed then DNS probably changed as well;
+        // otherwise check if cached settings have expired.
+        //
+        if (changed) {
+            changed = false;
+        } else {
+            if (lastRefresh >= 0) {
+                long currTime = System.currentTimeMillis();
+                if ((currTime - lastRefresh) < TIMEOUT) {
+                    return;
+                }
+            }
+        }
+
+        // load DNS configuration, update timestamp, create
+        // new HashMaps from the loaded configuration
+        //
+        loadDNSconfig0();
+
+        lastRefresh = System.currentTimeMillis();
+        searchlist = stringToList(os_searchlist);
+        nameservers = stringToList(os_nameservers);
+        os_searchlist = null;                       // can be GC'ed
+        os_nameservers = null;
+    }
+
+    DnsResolverConfiguration() {
+    }
+
+    @SuppressWarnings("unchecked") // clone()
+    public List<String> searchlist() {
+        lock.lock();
+        try {
+            loadConfig();
+
+            // List is mutable so return a shallow copy
+            return (List<String>) searchlist.clone();
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    @SuppressWarnings("unchecked") // clone()
+    public List<String> nameservers() {
+        lock.lock()
+        try {
+            loadConfig();
+
+            // List is mutable so return a shallow copy
+            return (List<String>) nameservers.clone();
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    // --- Address Change Listener
+
+    static class AddressChangeListener extends Thread {
+        public void run() {
+            for (; ; ) {
+                // wait for configuration to change
+                if (notifyAddrChange0() != 0)
+                    return;
+                lock.lock();
+                try {
+                    changed = true;
+                } finally {
+                    lock.unlock();
+                }
+            }
+        }
+    }
+
+
+    // --- Native methods --
+
+    static native void init0();
+
+    static native void loadDNSconfig0();
+
+    static native int notifyAddrChange0();
+
+    static {
+        System.loadLibrary("resolver");
+        init0();
+
+        // start the address listener thread
+        AddressChangeListener thr = new AddressChangeListener();
+        thr.setDaemon(true);
+        thr.start();
+    }
+}