More About DNS Queries
Normally if the Java standard library has the ability to doing something for which there exists external libraries I will use the standard library even if the standard library's approach is inelegant, so long as there isn't a performance reason not to. Today I've arrived at such an junction.In the standard library, if you want to issue DNS queries for anything besides A and PTR records, you must use JNDI. JNDI was really designed for use with LDAP but Sun managed to shoehorn some DNS into it. On the other hand there is dnsjava. An open-source java library for issuing all types of DNS queries.
Say I wanted to lookup the MX records for blogger.com. Using JNDI it would look like this:
String[] MX_RECORD = {"MX"};/** * Returns the MX records for domain sorted by preference or * null if no MX records where found. * * @param domain The domain name. * * @return The MX records for domain. * * @throws NamingException */
public ListgetMX( String domain ) throws NamingException { DirContext ctx = new InitialDirContext(); try { String query = "dns:/".concat( domain ); Attribute att = ctx.getAttributes( query, MX_RECORD ).get( "MX" ); if( null == att ) return null; Collection sorter = new TreeSet (); for( Enumeration e = att.getAll(); e.hasMoreElements(); ) sorter.add( ((String)e.nextElement()).trim() ); List sorted = new ArrayList ( sorter.size() ); for( String mx : sorter ) { /* Strip off preference integer. */ int offset = 0; int len = mx.length(); for( char c; offset < len && (Character.isDigit( c = mx.charAt( offset ) ) || Character.isWhitespace( c )); ) offset++;
/* Strip trailing dot (.) if it exists. */ if( '.' == mx.charAt( len - 1 ) ) len -= 1; mx = mx.substring( offset, len ); sorted.add( mx ); } return sorted; } finally { try { ctx.close(); } catch( NamingException ignore ) { } } }
Doing the same with dnsjava it would look like this:
static Comparator MX_SORTER = new Comparator() { public int compare( Object r1, Object r2 ) { return ((MXRecord)r1).getPriority() - ((MXRecord)r2).getPriority(); } }; /** * Returns the MX records for domain sorted by preference or * null if no MX records where found. * * @param domain The domain name. * * @return The MX records for domain. */ public static ListI'm praying that dnsjava outpeforms JNDI. I'm off to perform some micro benchmarks. I'll let you know how it went.getMX( String domain ) { try { Record[] records = new Lookup( domain, Type.MX ).run(); if( null == records ) return null; Arrays.sort( records, MX_SORTER ); List mx = new ArrayList ( records.length ); for( Record record : records ) { String host = ((MXRecord)record).getTarget().toString(); int len = host.length(); if( '.' == host.charAt( len - 1 ) ) host = host.substring( 0, len - 1 ); mx.add( host ); }
return mx; } catch( TextParseException e ) { throw new RuntimeException( e ); } }
What about anti-patterns and not using design patterns at all. Most patterns are not concerned on performance but on decoupling and cohesion.
ReplyDeletePedro, I have no idea what your comment is refering to.
ReplyDelete