noel 2003/01/28 09:31:29
Modified: . build.xml
proposals/imap2 build.xml
src/java/org/apache/james/dnsserver DNSServer.java
Added: lib dnsjava-1.3.2.jar
Log:
Serge Sozonoff's patches for updated dnsjava and auto-discovery
Revision Changes Path
1.1 jakarta-james/lib/dnsjava-1.3.2.jar
<<Binary file>>
1.120 +2 -2 jakarta-james/build.xml
Index: build.xml
===================================================================
RCS file: /home/cvs/jakarta-james/build.xml,v
retrieving revision 1.119
retrieving revision 1.120
diff -u -r1.119 -r1.120
--- build.xml 18 Jan 2003 23:22:34 -0000 1.119
+++ build.xml 28 Jan 2003 17:31:28 -0000 1.120
@@ -388,7 +388,7 @@
<include name="*.jar"/>
</lib>
<lib dir="lib">
- <include name="dnsjava-1.3.1.jar"/>
+ <include name="dnsjava-1.3.2.jar"/>
<include name="jakarta-oro-2.0.1.jar"/>
<include name="mm.mysql-2.0.14.jar"/>
<include name="mm.mysql.LICENCE"/>
1.7 +2 -2 jakarta-james/proposals/imap2/build.xml
Index: build.xml
===================================================================
RCS file: /home/cvs/jakarta-james/proposals/imap2/build.xml,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- build.xml 28 Jan 2003 12:55:22 -0000 1.6
+++ build.xml 28 Jan 2003 17:31:29 -0000 1.7
@@ -403,7 +403,7 @@
<include name="*.jar"/>
</lib>
<lib dir="lib">
- <include name="dnsjava-1.3.1.jar"/>
+ <include name="dnsjava-1.3.2.jar"/>
<include name="jakarta-oro-2.0.1.jar"/>
<include name="mm.mysql-2.0.14.jar"/>
<include name="mm.mysql.LICENCE"/>
1.14 +187 -66 jakarta-james/src/java/org/apache/james/dnsserver/DNSServer.java
Index: DNSServer.java
===================================================================
RCS file:
/home/cvs/jakarta-james/src/java/org/apache/james/dnsserver/DNSServer.java,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- DNSServer.java 18 Jan 2003 23:18:19 -0000 1.13
+++ DNSServer.java 28 Jan 2003 17:31:29 -0000 1.14
@@ -7,49 +7,51 @@
*/
package org.apache.james.dnsserver;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Comparator;
-import java.util.List;
-import java.util.Vector;
import org.apache.avalon.framework.activity.Initializable;
import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
-import org.apache.avalon.framework.logger.Logger;
+import org.xbill.DNS.Cache;
import org.xbill.DNS.Credibility;
import org.xbill.DNS.DClass;
import org.xbill.DNS.ExtendedResolver;
import org.xbill.DNS.FindServer;
+import org.xbill.DNS.Message;
import org.xbill.DNS.MXRecord;
import org.xbill.DNS.Name;
+import org.xbill.DNS.Rcode;
import org.xbill.DNS.Record;
import org.xbill.DNS.Resolver;
+import org.xbill.DNS.RRset;
+import org.xbill.DNS.SetResponse;
+import org.xbill.DNS.TextParseException;
import org.xbill.DNS.Type;
-import org.xbill.DNS.dns;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.*;
/**
- * Provides DNS client functionality to components running
+ * Provides DNS client functionality to services running
* inside James
- *
- * @version 1.0.0, 18/06/2000
*/
public class DNSServer
extends AbstractLogEnabled
implements Configurable, Initializable,
org.apache.james.services.DNSServer {
- private static class PriorityCompare implements Comparator {
- public int compare (Object a, Object b) {
- MXRecord ma = (MXRecord)a;
- MXRecord mb = (MXRecord)b;
- return ma.getPriority () - mb.getPriority ();
- }
- }
+ /**
+ * A resolver instance used to retrieve DNS records. This
+ * is a reference to a third party library object.
+ */
+ private Resolver resolver;
+
+ /**
+ * A TTL cache of results received from the DNS server. This
+ * is a reference to a third party library object.
+ */
+ private Cache cache;
/**
* Whether the DNS response is required to be authoritative
@@ -57,9 +59,14 @@
private byte dnsCredibility;
/**
- * The DNS servers to be used by this component
+ * The DNS servers to be used by this service
*/
- private Collection dnsServers = new Vector();
+ private List dnsServers = new ArrayList();
+
+ /**
+ * The MX Comparator used in the MX sort.
+ */
+ private Comparator mxComparator = new MXRecordComparator();
/**
* @see
org.apache.avalon.framework.configuration.Configurable#configure(Configuration)
@@ -67,9 +74,19 @@
public void configure( final Configuration configuration )
throws ConfigurationException {
-
- // TODO@ Maybe add some more config items to control DNS lookup retries and
- // timeouts
+ final boolean autodiscover =
+ configuration.getChild( "autodiscover" ).getValueAsBoolean( true );
+
+ if (autodiscover) {
+ getLogger().info("Autodiscovery is enabled - trying to discover your
system's DNS Servers");
+ String[] serversArray = FindServer.servers();
+ if (serversArray != null) {
+ for ( int i = 0; i < serversArray.length; i++ ) {
+ dnsServers.add(serversArray[ i ]);
+ getLogger().info("Adding autodiscovered server " +
serversArray[i]);
+ }
+ }
+ }
// Get the DNS servers that this service will use for lookups
final Configuration serversConfiguration = configuration.getChild(
"servers" );
@@ -80,8 +97,15 @@
dnsServers.add( serverConfigurations[ i ].getValue() );
}
+ if (dnsServers.isEmpty()) {
+ getLogger().info("No DNS servers have been specified or found by
autodiscovery - adding 127.0.0.1");
+ dnsServers.add("127.0.0.1");
+ }
+
final boolean authoritative =
configuration.getChild( "authoritative" ).getValueAsBoolean( false );
+ // TODO: Check to see if the credibility field is being used correctly.
From the
+ // docs I don't think so
dnsCredibility = authoritative ? Credibility.AUTH_ANSWER :
Credibility.NONAUTH_ANSWER;
}
@@ -91,34 +115,24 @@
public void initialize()
throws Exception {
-
- /**
- * A resolver instance used to retrieve DNS records. This
- * is a reference to a third party library object.
- */
- Resolver resolver = null;
-
- /**
- * Holds the list of dns servers used to create the new ExtendedResolver
instance
- */
- String[] serversArray;
-
getLogger().info("DNSServer init...");
- // If no DNS servers were configured, try and get the underlying systems
dns servers
- // otherwise use 127.0.0.1
- // Currently, this works if either the appropriate properties are set, the
OS has a unix-like /etc/resolv.conf,
- // or the system is Windows based with ipconfig or winipcfg.
+ // If no DNS servers were configured, default to local host
if (dnsServers.isEmpty()) {
- getLogger().info("Trying to locate your systems DNS Servers");
- serversArray = FindServer.servers();
- if (serversArray == null) {
- getLogger().info("No DNS servers found, defaulting to 127.0.0.1");
- serversArray = new String[]{"127.0.0.1"};
- }
- } else {
- //Create the extended resolver using config data
- serversArray = (String[])dnsServers.toArray(new String[0]);
+ try {
+ dnsServers.add( InetAddress.getLocalHost().getHostName() );
+ } catch ( UnknownHostException ue ) {
+ dnsServers.add( "127.0.0.1" );
+ }
+ }
+
+ //Create the extended resolver...
+ final String[] serversArray = (String[])dnsServers.toArray(new String[0]);
+
+ if (getLogger().isInfoEnabled()) {
+ for(int c = 0; c < serversArray.length; c++) {
+ getLogger().info("DNS Server is: " + serversArray[c]);
+ }
}
try {
@@ -128,30 +142,22 @@
throw uhe;
}
- if (getLogger().isInfoEnabled()) {
- for(int i = 0; i < serversArray.length; i++) {
- getLogger().info("DNS Server is: " + serversArray[i]);
- }
- }
-
- // set the resolver for the static class dns
- dns.setResolver(resolver);
+ cache = new Cache (DClass.IN);
getLogger().info("DNSServer ...init end");
}
/**
- * <p>Return a prioritized list of MX records
+ * <p>Return a prioritized unmodifiable list of MX records
* obtained from the server.</p>
*
- * @param the domain name to look up
+ * @param hostname domain name to look up
*
- * @return a list of MX records corresponding to
+ * @return a unmodifiable list of MX records corresponding to
* this mail domain name
*/
public Collection findMXRecords(String hostname) {
- Record answers[] = dns.getRecords(hostname, Type.MX, DClass.IN,
dnsCredibility);
-
+ Record answers[] = lookup(hostname, Type.MX);
List servers = new ArrayList();
try {
if (answers == null) {
@@ -163,17 +169,23 @@
mxAnswers[i] = (MXRecord)answers[i];
}
- Comparator prioritySort = new PriorityCompare ();
- Arrays.sort(mxAnswers, prioritySort);
+ Arrays.sort(mxAnswers, mxComparator);
for (int i = 0; i < mxAnswers.length; i++) {
servers.add(mxAnswers[i].getTarget ().toString ());
+ getLogger().info(new StringBuffer("Found MX record
").append(mxAnswers[i].getTarget ().toString ()).toString());
}
- return servers;
+ return Collections.unmodifiableCollection(servers);
} finally {
//If we found no results, we'll add the original domain name if
//it's a valid DNS entry
if (servers.size () == 0) {
+ StringBuffer logBuffer =
+ new StringBuffer(128)
+ .append("Couldn't resolve MX records for domain ")
+ .append(hostname)
+ .append(".");
+ getLogger().error(logBuffer.toString());
try {
InetAddress.getByName(hostname);
servers.add(hostname);
@@ -181,8 +193,117 @@
// The original domain name is not a valid host,
// so we can't add it to the server list. In this
// case we return an empty list of servers
+ logBuffer = new StringBuffer(128)
+ .append("Couldn't resolve IP address for host ")
+ .append(hostname)
+ .append(".");
+ getLogger().error(logBuffer.toString());
}
}
+ }
+ }
+
+ /**
+ * Looks up DNS records of the specified type for the specified name.
+ *
+ * This method is a public wrapper for the private implementation
+ * method
+ *
+ * @param name the name of the host to be looked up
+ * @param type the type of record desired
+ */
+ public Record[] lookup(String name, short type) {
+ return rawDNSLookup(name,false,type);
+ }
+
+ /**
+ * Looks up DNS records of the specified type for the specified name
+ *
+ * @param namestr the name of the host to be looked up
+ * @param querysent whether the query has already been sent to the DNS servers
+ * @param type the type of record desired
+ */
+ private Record[] rawDNSLookup(String namestr, boolean querysent, short type) {
+ Name name = null;
+ try {
+ name = Name.fromString(namestr, Name.root);
+ } catch (TextParseException tpe) {
+ // TODO: Figure out how to handle this correctly.
+ getLogger().error("Couldn't parse name " + namestr, tpe);
+ return null;
+ }
+ short dclass = DClass.IN;
+
+ Record [] answers;
+ int answerCount = 0, n = 0;
+
+ SetResponse cached = cache.lookupRecords(name, type, dnsCredibility);
+ if (cached.isSuccessful()) {
+ getLogger().info(new StringBuffer(256)
+ .append("Retrieving MX record for ")
+ .append(name).append(" from cache")
+ .toString());
+ RRset [] rrsets = cached.answers();
+ answerCount = 0;
+ for (int i = 0; i < rrsets.length; i++) {
+ answerCount += rrsets[i].size();
+ }
+
+ answers = new Record[answerCount];
+
+ for (int i = 0; i < rrsets.length; i++) {
+ Iterator iter = rrsets[i].rrs();
+ while (iter.hasNext()) {
+ Record r = (Record)iter.next();
+ answers[n++] = r;
+ }
+ }
+ }
+ else if (cached.isNXDOMAIN() || cached.isNXRRSET()) {
+ return null;
+ }
+ else if (querysent) {
+ return null;
+ }
+ else {
+ getLogger().info(new StringBuffer(256)
+ .append("Looking up MX record for ")
+ .append(name)
+ .toString());
+ Record question = Record.newRecord(name, type, dclass);
+ Message query = Message.newQuery(question);
+ Message response = null;
+
+ try {
+ response = resolver.send(query);
+ }
+ catch (Exception ex) {
+ getLogger().warn("Query error!", ex);
+ return null;
+ }
+
+ short rcode = response.getHeader().getRcode();
+ if (rcode == Rcode.NOERROR || rcode == Rcode.NXDOMAIN) {
+ cache.addMessage(response);
+ }
+
+ if (rcode != Rcode.NOERROR) {
+ return null;
+ }
+
+ return rawDNSLookup(namestr, true, type);
+ }
+
+ return answers;
+ }
+
+ private static class MXRecordComparator
+ implements Comparator {
+
+ public int compare (Object a, Object b) {
+ MXRecord ma = (MXRecord)a;
+ MXRecord mb = (MXRecord)b;
+ return ma.getPriority () - mb.getPriority ();
}
}
}
--
To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>