View Javadoc
1 /* 2 * Copyright (C) The Apache Software Foundation. All rights reserved. 3 * 4 * This software is published under the terms of the Apache Software License 5 * version 1.1, a copy of which has been included with this distribution in 6 * the LICENSE file. 7 */ 8 package org.masukomi.aspirin.core.dnsserver; 9 10 import org.masukomi.prefs.XMLClassPreferences; 11 12 import org.xbill.DNS.*; 13 14 import java.net.InetAddress; 15 import java.net.UnknownHostException; 16 17 import java.util.*; 18 import java.util.prefs.BackingStoreException; 19 20 21 /*** 22 * Provides DNS client functionality to components running 23 * inside James 24 * 25 * @version 1.0.0, 18/06/2000 26 * @author Serge Knystautas <sergek@lokitech.com> 27 */ 28 public class DNSServer { 29 //~ Static fields/initializers --------------------------------------------- 30 31 static XMLClassPreferences preferences; 32 33 34 35 /*** 36 * The component role used by components implementing this service 37 */ 38 static String ROLE = "org.masukomi.org.aspirin.core.dnsserver.DNSServer"; 39 40 /*** 41 * A TTL cache of results received from the DNS server. This 42 * is a reference to a third party library object. 43 */ 44 static private Cache cache; 45 46 /*** 47 * The DNS servers to be used by this component 48 */ 49 static private Collection dnsServers; 50 51 /*** 52 * A resolver instance used to retrieve DNS records. This 53 * is a reference to a third party library object. 54 */ 55 static private Resolver resolver; 56 57 /*** 58 * Whether the DNS response is required to be authoritative 59 */ 60 static private byte dnsCredibility = Credibility.NONAUTH_ANSWER; 61 62 static public boolean ready = false; 63 64 //~ Constructors ----------------------------------------------------------- 65 66 /*** 67 * Creates a new DNSServer object. 68 */ 69 public DNSServer() { 70 preferences = XMLClassPreferences.systemNodeForClass(this.getClass()); 71 configure(); 72 73 try { 74 initialize(); 75 } catch (Exception e) { 76 System.out.println( 77 "org.masukomi.aspirin.core.dnsserver.DNSServer() " + e); 78 } 79 } 80 81 //~ Methods ---------------------------------------------------------------- 82 83 /*** 84 * @see org.apache.avalon.framework.configuration.Configurable#configure(Configuration) 85 */ 86 87 //public void configure(final Configuration configuration) throws ConfigurationException { 88 public void configure() { 89 // Get the DNS servers that this service will use for lookups 90 91 /*final Configuration serversConfiguration = configuration.getChild( 92 "servers"); 93 final Configuration[] serverConfigurations = serversConfiguration 94 .getChildren("server"); 95 */ 96 String[] serverConfigurations; 97 dnsServers = new Vector(); 98 try { 99 100 try { 101 102 serverConfigurations = preferences.keys(); 103 if (serverConfigurations != null){ 104 for (int i = 0; i < serverConfigurations.length; i++) { 105 //dnsServers.add(serverConfigurations[i].getValue()); 106 dnsServers.add(serverConfigurations[i]); 107 System.out.println("configured with this DNS " + serverConfigurations[i]); 108 } 109 } 110 ready = true; 111 } catch (NullPointerException npe){ 112 System.out.println("DNSServer.configure()" + npe); 113 114 } 115 116 // for testing only 117 //dnsServers.add("216.35.6.241"); 118 119 } catch (BackingStoreException e) { 120 } 121 122 /*final boolean authoritative = configuration.getChild("authoritative") 123 .getValueAsBoolean(false); 124 dnsCredibility = authoritative ? Credibility.AUTH_ANSWER 125 : Credibility.NONAUTH_ANSWER; 126 */ 127 } 128 129 /*** 130 * <p>Return a prioritized list of MX records 131 * obtained from the server.</p> 132 * 133 * <p>TODO: This should actually return a List, not 134 * a Collection.</p> 135 * 136 * @param the domain name to look up 137 * 138 * @return a list of MX records corresponding to 139 * this mail domain name 140 */ 141 static public Collection findMXRecords(String hostname) { 142 Record[] answers = lookup(hostname, Type.MX); 143 144 // TODO: Determine why this collection is synchronized 145 Collection servers = new Vector(); 146 147 try { 148 if (answers == null) { 149 return servers; 150 } 151 152 MXRecord[] mxAnswers = new MXRecord[answers.length]; 153 154 for (int i = 0; i < answers.length; i++) { 155 mxAnswers[i] = (MXRecord) answers[i]; 156 } 157 158 // TODO: Convert this to a static class instance 159 // No need to pay the object creation cost 160 // on each call 161 Comparator prioritySort = new Comparator() { 162 public int compare(Object a, Object b) { 163 MXRecord ma = (MXRecord) a; 164 MXRecord mb = (MXRecord) b; 165 166 return ma.getPriority() - mb.getPriority(); 167 } 168 }; 169 170 Arrays.sort(mxAnswers, prioritySort); 171 172 for (int i = 0; i < mxAnswers.length; i++) { 173 servers.add(mxAnswers[i].getTarget().toString()); 174 } 175 176 return servers; 177 } finally { 178 //If we found no results, we'll add the original domain name if 179 //it's a valid DNS entry 180 if (servers.size() == 0) { 181 try { 182 InetAddress.getByName(hostname); 183 servers.add(hostname); 184 } catch (UnknownHostException uhe) { 185 // The original domain name is not a valid host, 186 // so we can't add it to the server list. In this 187 // case we return an empty list of servers 188 } 189 } 190 } 191 } 192 193 /*** 194 * @see org.apache.avalon.framework.activity.Initializable#initialize() 195 */ 196 public void initialize() throws Exception { 197 //getLogger().info("DNSServer init..."); 198 // If no DNS servers were configured, default to local host 199 if (dnsServers.isEmpty()) { 200 try { 201 dnsServers.add(InetAddress.getLocalHost().getHostName()); 202 } catch (UnknownHostException ue) { 203 dnsServers.add("127.0.0.1"); 204 } 205 } 206 207 /*if (getLogger().isInfoEnabled()) { 208 for (Iterator i = dnsServers.iterator(); i.hasNext();) { 209 getLogger().info("DNS Server is: " + i.next()); 210 } 211 }*/ 212 213 //Create the extended resolver... 214 final String[] serversArray = (String[]) dnsServers.toArray(new String[0]); 215 216 try { 217 resolver = new ExtendedResolver(serversArray); 218 } catch (UnknownHostException uhe) { 219 //getLogger().fatalError("DNS service could not be initialized. The DNS servers specified are not recognized hosts.", 220 // uhe); 221 throw uhe; 222 } 223 224 cache = new Cache(DClass.IN); 225 226 //getLogger().info("DNSServer ...init end"); 227 } 228 229 /*** 230 * Looks up DNS records of the specified type for the specified name. 231 * 232 * This method is a public wrapper for the private implementation 233 * method 234 * 235 * @param name the name of the host to be looked up 236 * @param type the type of record desired 237 */ 238 static public Record[] lookup(String name, short type) { 239 return rawDNSLookup(name, false, type); 240 } 241 242 /*** 243 * Looks up DNS records of the specified type for the specified name 244 * 245 * @param name the name of the host to be looked up 246 * @param querysent whether the query has already been sent to the DNS servers 247 * @param type the type of record desired 248 */ 249 static private Record[] rawDNSLookup(String namestr, boolean querysent, short type) { 250 Name name = new Name(namestr); 251 short dclass = DClass.IN; 252 253 Record[] answers; 254 int answerCount = 0; 255 int n = 0; 256 Enumeration e; 257 258 SetResponse cached = cache.lookupRecords(name, type, dnsCredibility); 259 260 if (cached.isSuccessful()) { 261 RRset[] rrsets = cached.answers(); 262 answerCount = 0; 263 264 for (int i = 0; i < rrsets.length; i++) { 265 answerCount += rrsets[i].size(); 266 } 267 268 answers = new Record[answerCount]; 269 270 for (int i = 0; i < rrsets.length; i++) { 271 e = rrsets[i].rrs(); 272 273 while (e.hasMoreElements()) { 274 Record r = (Record) e.nextElement(); 275 answers[n++] = r; 276 } 277 } 278 } else if (cached.isNXDOMAIN() || cached.isNXRRSET()) { 279 return null; 280 } else if (querysent) { 281 return null; 282 } else { 283 Record question = Record.newRecord(name, type, dclass); 284 org.xbill.DNS.Message query = org.xbill.DNS.Message.newQuery(question); 285 org.xbill.DNS.Message response; 286 287 try { 288 response = resolver.send(query); 289 } catch (Exception ex) { 290 return null; 291 } 292 293 short rcode = response.getHeader().getRcode(); 294 295 if ((rcode == Rcode.NOERROR) || (rcode == Rcode.NXDOMAIN)) { 296 cache.addMessage(response); 297 } 298 299 if (rcode != Rcode.NOERROR) { 300 return null; 301 } 302 303 return rawDNSLookup(namestr, true, type); 304 } 305 306 return answers; 307 } 308 } 309

This page was automatically generated by Maven