1 /* 2 * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.net.dns; 27 28 import java.util.List; 29 import java.util.LinkedList; 30 import java.util.StringTokenizer; 31 32 /* 33 * An implementation of sun.net.ResolverConfiguration for Windows. 34 */ 35 36 public class ResolverConfigurationImpl 37 extends ResolverConfiguration 38 { 39 // Lock helds whilst loading configuration or checking 40 private static Object lock = new Object(); 41 42 // Resolver options 43 private final Options opts; 44 45 // Addreses have changed 46 private static boolean changed = false; 47 48 // Time of last refresh. 49 private static long lastRefresh = -1; 50 51 // Cache timeout (120 seconds) - should be converted into property 52 // or configured as preference in the future. 53 private static final int TIMEOUT = 120000; 54 55 // DNS suffix list and name servers populated by native method 56 private static String os_searchlist; 57 private static String os_nameservers; 58 59 // Cached lists 60 private static LinkedList<String> searchlist; 61 private static LinkedList<String> nameservers; 62 63 // Parse string that consists of token delimited by space or commas 64 // and return LinkedHashMap 65 private LinkedList<String> stringToList(String str) { 66 LinkedList<String> ll = new LinkedList<String>(); 67 68 // comma and space are valid delimites 69 StringTokenizer st = new StringTokenizer(str, ", "); 70 while (st.hasMoreTokens()) { 71 String s = st.nextToken(); 72 if (!ll.contains(s)) { 73 ll.add(s); 74 } 75 } 76 return ll; 77 } 78 79 // Load DNS configuration from OS 80 81 private void loadConfig() { 82 assert Thread.holdsLock(lock); 83 84 // if address have changed then DNS probably changed aswell; 85 // otherwise check if cached settings have expired. 86 // 87 if (changed) { 88 changed = false; 89 } else { 90 if (lastRefresh >= 0) { 91 long currTime = System.currentTimeMillis(); 92 if ((currTime - lastRefresh) < TIMEOUT) { 93 return; 94 } 95 } 96 } 97 98 // load DNS configuration, update timestamp, create 99 // new HashMaps from the loaded configuration 100 // 101 loadDNSconfig0(); 102 103 lastRefresh = System.currentTimeMillis(); 104 searchlist = stringToList(os_searchlist); 105 nameservers = stringToList(os_nameservers); 106 os_searchlist = null; // can be GC'ed 107 os_nameservers = null; 108 } 109 110 ResolverConfigurationImpl() { 111 opts = new OptionsImpl(); 112 } 113 114 @SuppressWarnings("unchecked") // clone() 115 public List<String> searchlist() { 116 synchronized (lock) { 117 loadConfig(); 118 119 // List is mutable so return a shallow copy 120 return (List<String>)searchlist.clone(); 121 } 122 } 123 124 @SuppressWarnings("unchecked") // clone() 125 public List<String> nameservers() { 126 synchronized (lock) { 127 loadConfig(); 128 129 // List is mutable so return a shallow copy 130 return (List<String>)nameservers.clone(); 131 } 132 } 133 134 public Options options() { 135 return opts; 136 } 137 138 // --- Address Change Listener 139 140 static class AddressChangeListener extends Thread { 141 public void run() { 142 for (;;) { 143 // wait for configuration to change 144 if (notifyAddrChange0() != 0) 145 return; 146 synchronized (lock) { 147 changed = true; 148 } 149 } 150 } 151 } 152 153 154 // --- Native methods -- 155 156 static native void init0(); 157 158 static native void loadDNSconfig0(); 159 160 static native int notifyAddrChange0(); 161 162 static { 163 java.security.AccessController.doPrivileged( 164 new sun.security.action.LoadLibraryAction("net")); 165 init0(); 166 167 // start the address listener thread 168 AddressChangeListener thr = new AddressChangeListener(); 169 thr.setDaemon(true); 170 thr.start(); 171 } 172 } 173 174 /** 175 * Implementation of {@link ResolverConfiguration.Options} 176 */ 177 class OptionsImpl extends ResolverConfiguration.Options { 178 }