Package org.apache.james.dnsserver

Source Code of org.apache.james.dnsserver.DNSServer

/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE file.
*/
package org.apache.james.dnsserver;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Vector;
import org.apache.avalon.framework.activity.Initializable;
import org.apache.avalon.framework.component.Component;
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.AbstractLoggable;
import org.apache.avalon.phoenix.Block;
import org.apache.james.transport.Resources;
import org.xbill.DNS.Cache;
import org.xbill.DNS.Credibility;
import org.xbill.DNS.DClass;
import org.xbill.DNS.ExtendedResolver;
import org.xbill.DNS.Header;
import org.xbill.DNS.MXRecord;
import org.xbill.DNS.Message;
import org.xbill.DNS.Name;
import org.xbill.DNS.RRset;
import org.xbill.DNS.Rcode;
import org.xbill.DNS.Record;
import org.xbill.DNS.Resolver;
import org.xbill.DNS.SetResponse;
import org.xbill.DNS.Type;

/**
* @version 1.0.0, 18/06/2000
* @author  Serge Knystautas <sergek@lokitech.com>
*/
public class DNSServer
    extends AbstractLoggable
    implements Block, Configurable, Initializable,
    org.apache.james.services.DNSServer {

    private Resolver resolver;
    private Cache cache;
    private byte dnsCredibility;
    private Collection servers = new Vector();

    public void configure( final Configuration configuration )
        throws ConfigurationException {

        // Get this servers that this block will use for lookups
        final Configuration serversConfiguration = configuration.getChild( "servers" );
        final Configuration[] serverConfigurations =
            serversConfiguration.getChildren( "server" );

        for ( int i = 0; i < serverConfigurations.length; i++ )
        {
            servers.add( serverConfigurations[ i ].getValue() );
        }

        final boolean authoritative =
            configuration.getChild( "authoritative" ).getValueAsBoolean( false );
        dnsCredibility = authoritative ? Credibility.AUTH_ANSWER : Credibility.NONAUTH_ANSWER;
    }

    public void initialize()
        throws Exception {

        getLogger().info("DNSServer init...");

        if (servers.isEmpty()) {
            try {
                servers.add( InetAddress.getLocalHost().getHostName() );
            } catch ( UnknownHostException ue ) {
                servers.add( "127.0.0.1" );
            }
        }

        for (Iterator i = servers.iterator(); i.hasNext(); ) {
            getLogger().info("DNS Servers is: " + i.next());
        }

        //Create the extended resolver...
        final String serversArray[] = (String[])servers.toArray(new String[0]);
        resolver = new ExtendedResolver( serversArray );

        cache = new Cache (DClass.IN);

        getLogger().info("DNSServer ...init end");
    }

    public Collection findMXRecords(String hostname) {
        Record answers[] = lookup(hostname, Type.MX);

        Collection servers = new Vector ();
        try {
            if (answers == null) {
                return servers;
            }

            MXRecord mxAnswers[] = new MXRecord[answers.length];
            for (int i = 0; i < answers.length; i++) {
                mxAnswers[i] = (MXRecord)answers[i];
            }

            Comparator prioritySort = new Comparator () {
                    public int compare (Object a, Object b) {
                        MXRecord ma = (MXRecord)a;
                        MXRecord mb = (MXRecord)b;
                        return ma.getPriority () - mb.getPriority ();
                    }
                };

            Arrays.sort(mxAnswers, prioritySort);

            for (int i = 0; i < mxAnswers.length; i++) {
                servers.add(mxAnswers[i].getTarget ().toString ());
            }
            return 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) {
                try {
                    InetAddress.getByName(hostname);
                    servers.add(hostname);
                } catch (UnknownHostException uhe) {
                }
            }
        }
    }

    public Record[] lookup(String name, short type) {
        return rawDNSLookup(name,false,type);
    }

    private Record[] rawDNSLookup(String namestr, boolean querysent, short type) {
        Name name = new Name(namestr);
        short dclass = DClass.IN;

        Record [] answers;
        int answerCount = 0, n = 0;
        Enumeration e;

        SetResponse cached = cache.lookupRecords(name, type, dnsCredibility);
        if (cached.isSuccessful()) {
            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++) {
                e = rrsets[i].rrs();
                while (e.hasMoreElements()) {
                    Record r = (Record)e.nextElement();
                    answers[n++] = r;
                }
            }
        }
        else if (cached.isNXDOMAIN() || cached.isNXRRSET()) {
            return null;
        }
        else if (querysent) {
            return null;
        }
        else {
            Record question = Record.newRecord(name, type, dclass);
            org.xbill.DNS.Message query = org.xbill.DNS.Message.newQuery(question);
            org.xbill.DNS.Message response;

            try {
                response = resolver.send(query);
            }
            catch (Exception 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.MX);
        }

        return answers;
    }
}
TOP

Related Classes of org.apache.james.dnsserver.DNSServer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.