42 * A DnsContextFactory serves as the initial context factory for DNS. 43 * 44 * <p> When an initial context is being created, the environment 45 * property "java.naming.provider.url" should contain a DNS pseudo-URL 46 * (see DnsUrl) or a space-separated list of them. Multiple URLs must 47 * all have the same domain value. 48 * If the property is not set, the default "dns:" is used. 49 * 50 * @author Scott Seligman 51 */ 52 53 54 public class DnsContextFactory implements InitialContextFactory { 55 56 private static final String DEFAULT_URL = "dns:"; 57 private static final int DEFAULT_PORT = 53; 58 59 60 public Context getInitialContext(Hashtable<?,?> env) throws NamingException { 61 if (env == null) { 62 env = new Hashtable(5); 63 } 64 return urlToContext(getInitCtxUrl(env), env); 65 } 66 67 public static DnsContext getContext(String domain, 68 String[] servers, Hashtable<?,?> env) 69 throws NamingException { 70 return new DnsContext(domain, servers, env); 71 } 72 73 /* 74 * "urls" are used to determine the servers, but any domain 75 * components are overridden by "domain". 76 */ 77 public static DnsContext getContext(String domain, 78 DnsUrl[] urls, Hashtable env) 79 throws NamingException { 80 81 String[] servers = serversForUrls(urls); 82 DnsContext ctx = getContext(domain, servers, env); 83 if (platformServersUsed(urls)) { 84 ctx.setProviderUrl(constructProviderUrl(domain, servers)); 85 } 86 return ctx; 87 } 88 89 /* 90 * Public for use by product test suite. 91 */ 92 public static boolean platformServersAvailable() { 93 return !filterNameServers( 94 ResolverConfiguration.open().nameservers(), true 95 ).isEmpty(); 96 } 97 98 private static Context urlToContext(String url, Hashtable env) 99 throws NamingException { 100 101 DnsUrl[] urls; 102 try { 103 urls = DnsUrl.fromList(url); 104 } catch (MalformedURLException e) { 105 throw new ConfigurationException(e.getMessage()); 106 } 107 if (urls.length == 0) { 108 throw new ConfigurationException( 109 "Invalid DNS pseudo-URL(s): " + url); 110 } 111 String domain = urls[0].getDomain(); 112 113 // If multiple urls, all must have the same domain. 114 for (int i = 1; i < urls.length; i++) { 115 if (!domain.equalsIgnoreCase(urls[i].getDomain())) { 116 throw new ConfigurationException( 117 "Conflicting domains: " + url); 118 } 195 path = "/" + UrlUtil.encode(domain, "ISO-8859-1"); 196 } catch (java.io.UnsupportedEncodingException e) { 197 // assert false : "ISO-Latin-1 charset unavailable"; 198 } 199 } 200 201 StringBuffer buf = new StringBuffer(); 202 for (int i = 0; i < servers.length; i++) { 203 if (i > 0) { 204 buf.append(' '); 205 } 206 buf.append("dns://").append(servers[i]).append(path); 207 } 208 return buf.toString(); 209 } 210 211 /* 212 * Reads environment to find URL(s) of initial context. 213 * Default URL is "dns:". 214 */ 215 private static String getInitCtxUrl(Hashtable env) { 216 String url = (String) env.get(Context.PROVIDER_URL); 217 return ((url != null) ? url : DEFAULT_URL); 218 } 219 220 /** 221 * Removes any DNS server that's not permitted to access 222 * @param input the input server[:port] list, must not be null 223 * @param oneIsEnough return output once there exists one ok 224 * @return the filtered list, all non-permitted input removed 225 */ 226 private static List filterNameServers(List input, boolean oneIsEnough) { 227 SecurityManager security = System.getSecurityManager(); 228 if (security == null || input == null || input.isEmpty()) { 229 return input; 230 } else { 231 List output = new ArrayList(); 232 for (Object o: input) { 233 if (o instanceof String) { 234 String platformServer = (String)o; 235 int colon = platformServer.indexOf(':', 236 platformServer.indexOf(']') + 1); 237 238 int p = (colon < 0) 239 ? DEFAULT_PORT 240 : Integer.parseInt( 241 platformServer.substring(colon + 1)); 242 String s = (colon < 0) 243 ? platformServer 244 : platformServer.substring(0, colon); 245 try { 246 security.checkConnect(s, p); 247 output.add(platformServer); 248 if (oneIsEnough) { 249 return output; 250 } 251 } catch (SecurityException se) { 252 continue; 253 } 254 } 255 } 256 return output; 257 } 258 } 259 } | 42 * A DnsContextFactory serves as the initial context factory for DNS. 43 * 44 * <p> When an initial context is being created, the environment 45 * property "java.naming.provider.url" should contain a DNS pseudo-URL 46 * (see DnsUrl) or a space-separated list of them. Multiple URLs must 47 * all have the same domain value. 48 * If the property is not set, the default "dns:" is used. 49 * 50 * @author Scott Seligman 51 */ 52 53 54 public class DnsContextFactory implements InitialContextFactory { 55 56 private static final String DEFAULT_URL = "dns:"; 57 private static final int DEFAULT_PORT = 53; 58 59 60 public Context getInitialContext(Hashtable<?,?> env) throws NamingException { 61 if (env == null) { 62 env = new Hashtable<>(5); 63 } 64 return urlToContext(getInitCtxUrl(env), env); 65 } 66 67 public static DnsContext getContext(String domain, 68 String[] servers, Hashtable<?,?> env) 69 throws NamingException { 70 return new DnsContext(domain, servers, env); 71 } 72 73 /* 74 * "urls" are used to determine the servers, but any domain 75 * components are overridden by "domain". 76 */ 77 public static DnsContext getContext(String domain, 78 DnsUrl[] urls, Hashtable<?,?> env) 79 throws NamingException { 80 81 String[] servers = serversForUrls(urls); 82 DnsContext ctx = getContext(domain, servers, env); 83 if (platformServersUsed(urls)) { 84 ctx.setProviderUrl(constructProviderUrl(domain, servers)); 85 } 86 return ctx; 87 } 88 89 /* 90 * Public for use by product test suite. 91 */ 92 public static boolean platformServersAvailable() { 93 return !filterNameServers( 94 ResolverConfiguration.open().nameservers(), true 95 ).isEmpty(); 96 } 97 98 private static Context urlToContext(String url, Hashtable<?,?> env) 99 throws NamingException { 100 101 DnsUrl[] urls; 102 try { 103 urls = DnsUrl.fromList(url); 104 } catch (MalformedURLException e) { 105 throw new ConfigurationException(e.getMessage()); 106 } 107 if (urls.length == 0) { 108 throw new ConfigurationException( 109 "Invalid DNS pseudo-URL(s): " + url); 110 } 111 String domain = urls[0].getDomain(); 112 113 // If multiple urls, all must have the same domain. 114 for (int i = 1; i < urls.length; i++) { 115 if (!domain.equalsIgnoreCase(urls[i].getDomain())) { 116 throw new ConfigurationException( 117 "Conflicting domains: " + url); 118 } 195 path = "/" + UrlUtil.encode(domain, "ISO-8859-1"); 196 } catch (java.io.UnsupportedEncodingException e) { 197 // assert false : "ISO-Latin-1 charset unavailable"; 198 } 199 } 200 201 StringBuffer buf = new StringBuffer(); 202 for (int i = 0; i < servers.length; i++) { 203 if (i > 0) { 204 buf.append(' '); 205 } 206 buf.append("dns://").append(servers[i]).append(path); 207 } 208 return buf.toString(); 209 } 210 211 /* 212 * Reads environment to find URL(s) of initial context. 213 * Default URL is "dns:". 214 */ 215 private static String getInitCtxUrl(Hashtable<?,?> env) { 216 String url = (String) env.get(Context.PROVIDER_URL); 217 return ((url != null) ? url : DEFAULT_URL); 218 } 219 220 /** 221 * Removes any DNS server that's not permitted to access 222 * @param input the input server[:port] list, must not be null 223 * @param oneIsEnough return output once there exists one ok 224 * @return the filtered list, all non-permitted input removed 225 */ 226 private static List<String> filterNameServers(List<String> input, boolean oneIsEnough) { 227 SecurityManager security = System.getSecurityManager(); 228 if (security == null || input == null || input.isEmpty()) { 229 return input; 230 } else { 231 List<String> output = new ArrayList<>(); 232 for (String platformServer: input) { 233 int colon = platformServer.indexOf(':', 234 platformServer.indexOf(']') + 1); 235 236 int p = (colon < 0) 237 ? DEFAULT_PORT 238 : Integer.parseInt( 239 platformServer.substring(colon + 1)); 240 String s = (colon < 0) 241 ? platformServer 242 : platformServer.substring(0, colon); 243 try { 244 security.checkConnect(s, p); 245 output.add(platformServer); 246 if (oneIsEnough) { 247 return output; 248 } 249 } catch (SecurityException se) { 250 continue; 251 } 252 } 253 return output; 254 } 255 } 256 } |