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