panda.net.dns.MXLookup Maven / Gradle / Ivy
package panda.net.dns;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import panda.lang.Collections;
import panda.lang.Strings;
import panda.lang.collection.ExpireMap;
import panda.lang.collection.LRUMap;
import panda.lang.time.DateTimes;
import panda.log.Log;
import panda.log.Logs;
/**
* A utility class for mx records lookup.
*/
public class MXLookup {
private static final Log log = Logs.getLog(MXLookup.class);
/**
* default expire time: 30m
*/
public static final long DEFAULT_CACHE_MAXAGE = DateTimes.MS_MINUTE * 30;
/**
* default cache limit: 100
*/
public static final int DEFAULT_CACHE_LIMIT = 100;
protected static Map> cache;
/**
* init cache
* @param limit limit count
* @param expire expire (millisecond)
*/
public static synchronized void initCache(int limit, long expire) {
ExpireMap> em = new ExpireMap>(new LRUMap>(limit), expire);
cache = Collections.synchronizedMap(em);
}
private static synchronized List getCachedHosts(String hostname) {
return cache == null ? null : cache.get(hostname);
}
private static synchronized void putHostsToCache(String hostname, List hosts) {
if (cache == null) {
initCache(DEFAULT_CACHE_LIMIT, DEFAULT_CACHE_MAXAGE);
}
cache.put(hostname, hosts);
}
/**
* lookup mx records by hostname
* @param hostname host name
* @return server list
* @throws NamingException if a naming error occurs
*/
public static List lookup(String hostname) throws NamingException {
List hosts = getCachedHosts(hostname);
if (Collections.isNotEmpty(hosts)) {
return hosts;
}
if (log.isDebugEnabled()) {
log.debug("MX Lookup for " + hostname);
}
Hashtable env = new Hashtable();
env.put("java.naming.factory.initial", "com.sun.jndi.dns.DnsContextFactory");
DirContext ictx = new InitialDirContext(env);
Attributes attrs = ictx.getAttributes(hostname, new String[] { "MX" });
Attribute attr = attrs.get("MX");
// if we don't have an MX record, try the machine itself
if ((attr == null) || (attr.size() == 0)) {
attrs = ictx.getAttributes(hostname, new String[] { "A" });
attr = attrs.get("A");
if (attr == null) {
throw new NamingException("No match for name '" + hostname + "'");
}
}
hosts = new ArrayList(attr.size());
for (int i = 0; i < attr.size(); i++) {
String[] ss = Strings.split((String)attr.get(i), ' ');
if (ss.length == 1) {
hosts.add(ss[0]);
}
else if (ss[1].endsWith(".")) {
hosts.add(ss[1].substring(0, (ss[1].length() - 1)));
}
else {
hosts.add(ss[1]);
}
}
putHostsToCache(hostname, hosts);
return hosts;
}
}