/*
 * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.jndi.dns;


import java.util.Enumeration;
import java.util.Hashtable;

import javax.naming.*;
import javax.naming.directory.*;
import javax.naming.spi.DirectoryManager;

import com.sun.jndi.toolkit.ctx.*;


/**
 * A DnsContext is a directory context representing a DNS node.
 *
 * @author Scott Seligman
 */


public class DnsContext extends ComponentDirContext {

    DnsName domain;             // fully-qualified domain name of this context,
                                // with a root (empty) label at position 0
    Hashtable environment;
    private boolean envShared;  // true if environment is possibly shared
                                // and so must be copied on write
    private boolean parentIsDns;        // was this DnsContext created by
                                        // another?  see composeName()
    private String[] servers;
    private Resolver resolver;

    private boolean authoritative;      // must all responses be authoritative?
    private boolean recursion;          // request recursion on queries?
    private int timeout;                // initial timeout on UDP queries in ms
    private int retries;                // number of UDP retries

    static final NameParser nameParser = new DnsNameParser();

    // Timeouts for UDP queries use exponential backoff:  each retry
    // is for twice as long as the last.  The following constants set
    // the defaults for the initial timeout (in ms) and the number of
    // retries, and name the environment properties used to override
    // these defaults.
    private static final int DEFAULT_INIT_TIMEOUT = 1000;
    private static final int DEFAULT_RETRIES = 4;
    private static final String INIT_TIMEOUT =
                                          "com.sun.jndi.dns.timeout.initial";
    private static final String RETRIES = "com.sun.jndi.dns.timeout.retries";

    // The resource record type and class to use for lookups, and the
    // property used to modify them
    private CT lookupCT;
    private static final String LOOKUP_ATTR = "com.sun.jndi.dns.lookup.attr";

    // Property used to disallow recursion on queries
    private static final String RECURSION = "com.sun.jndi.dns.recursion";

    // ANY == ResourceRecord.QCLASS_STAR == ResourceRecord.QTYPE_STAR
    private static final int ANY = ResourceRecord.QTYPE_STAR;

    // The zone tree used for list operations
    private static final ZoneNode zoneTree = new ZoneNode(null);


    /**
     * Returns a DNS context for a given domain and servers.
     * Each server is of the form "server[:port]".
     * IPv6 literal host names include delimiting brackets.
     * There must be at least one server.
     * The environment must not be null; it is cloned before being stored.
     */
    public DnsContext(String domain, String[] servers, Hashtable environment)
            throws NamingException {

        this.domain = new DnsName(domain.endsWith(".")
                                  ? domain
                                  : domain + ".");
        this.servers = servers;
        this.environment = (Hashtable) environment.clone();
        envShared = false;
        parentIsDns = false;
        resolver = null;

        initFromEnvironment();
    }

    /*
     * Returns a clone of a DNS context, just like DnsContext(DnsContext)
     * but with a different domain name and with parentIsDns set to true.
     */
    DnsContext(DnsContext ctx, DnsName domain) {
        this(ctx);
        this.domain = domain;
        parentIsDns = true;
    }

    /*
     * Returns a clone of a DNS context.  The context's modifiable
     * private state is independent of the original's (so closing one
     * context, for example, won't close the other).  The two contexts
     * share <tt>environment</tt>, but it's copy-on-write so there's
     * no conflict.
     */
    private DnsContext(DnsContext ctx) {
        environment = ctx.environment;
        envShared = ctx.envShared = true;
        parentIsDns = ctx.parentIsDns;
        domain = ctx.domain;
        servers = ctx.servers;
        resolver = ctx.resolver;
        authoritative = ctx.authoritative;
        recursion = ctx.recursion;
        timeout = ctx.timeout;
        retries = ctx.retries;
        lookupCT = ctx.lookupCT;
    }

    public void close() {
        if (resolver != null) {
            resolver.close();
            resolver = null;
        }
    }


    //---------- Environment operations

    /*
     * Override default with a noncloning version.
     */
    protected Hashtable p_getEnvironment() {
        return environment;
    }

    public Hashtable getEnvironment() throws NamingException {
        return (Hashtable) environment.clone();
    }

    public Object addToEnvironment(String propName, Object propVal)
            throws NamingException {

        if (propName.equals(LOOKUP_ATTR)) {
            lookupCT = getLookupCT((String) propVal);
        } else if (propName.equals(Context.AUTHORITATIVE)) {
            authoritative = "true".equalsIgnoreCase((String) propVal);
        } else if (propName.equals(RECURSION)) {
            recursion = "true".equalsIgnoreCase((String) propVal);
        } else if (propName.equals(INIT_TIMEOUT)) {
            int val = Integer.parseInt((String) propVal);
            if (timeout != val) {
                timeout = val;
                resolver = null;
            }
        } else if (propName.equals(RETRIES)) {
            int val = Integer.parseInt((String) propVal);
            if (retries != val) {
                retries = val;
                resolver = null;
            }
        }

        if (!envShared) {
            return environment.put(propName, propVal);
        } else if (environment.get(propName) != propVal) {
            // copy on write
            environment = (Hashtable) environment.clone();
            envShared = false;
            return environment.put(propName, propVal);
        } else {
            return propVal;
        }
    }

    public Object removeFromEnvironment(String propName)
            throws NamingException {

        if (propName.equals(LOOKUP_ATTR)) {
            lookupCT = getLookupCT(null);
        } else if (propName.equals(Context.AUTHORITATIVE)) {
            authoritative = false;
        } else if (propName.equals(RECURSION)) {
            recursion = true;
        } else if (propName.equals(INIT_TIMEOUT)) {
            if (timeout != DEFAULT_INIT_TIMEOUT) {
                timeout = DEFAULT_INIT_TIMEOUT;
                resolver = null;
            }
        } else if (propName.equals(RETRIES)) {
            if (retries != DEFAULT_RETRIES) {
                retries = DEFAULT_RETRIES;
                resolver = null;
            }
        }

        if (!envShared) {
            return environment.remove(propName);
        } else if (environment.get(propName) != null) {
            // copy-on-write
            environment = (Hashtable) environment.clone();
            envShared = false;
            return environment.remove(propName);
        } else {
            return null;
        }
    }

    /*
     * Update PROVIDER_URL property.  Call this only when environment
     * is not being shared.
     */
    void setProviderUrl(String url) {
        // assert !envShared;
        environment.put(Context.PROVIDER_URL, url);
    }

    /*
     * Read environment properties and set parameters.
     */
    private void initFromEnvironment()
            throws InvalidAttributeIdentifierException {

        lookupCT = getLookupCT((String) environment.get(LOOKUP_ATTR));
        authoritative = "true".equalsIgnoreCase((String)
                                       environment.get(Context.AUTHORITATIVE));
        String val = (String) environment.get(RECURSION);
        recursion = ((val == null) ||
                     "true".equalsIgnoreCase(val));
        val = (String) environment.get(INIT_TIMEOUT);
        timeout = (val == null)
            ? DEFAULT_INIT_TIMEOUT
            : Integer.parseInt(val);
        val = (String) environment.get(RETRIES);
        retries = (val == null)
            ? DEFAULT_RETRIES
            : Integer.parseInt(val);
    }

    private CT getLookupCT(String attrId)
            throws InvalidAttributeIdentifierException {
        return (attrId == null)
            ? new CT(ResourceRecord.CLASS_INTERNET, ResourceRecord.TYPE_TXT)
            : fromAttrId(attrId);
    }


    //---------- Naming operations

    public Object c_lookup(Name name, Continuation cont)
            throws NamingException {

        cont.setSuccess();
        if (name.isEmpty()) {
            DnsContext ctx = new DnsContext(this);
            ctx.resolver = new Resolver(servers, timeout, retries);
                                                // clone for parallelism
            return ctx;
        }
        try {
            DnsName fqdn = fullyQualify(name);
            ResourceRecords rrs =
                getResolver().query(fqdn, lookupCT.rrclass, lookupCT.rrtype,
                                    recursion, authoritative);
            Attributes attrs = rrsToAttrs(rrs, null);
            DnsContext ctx = new DnsContext(this, fqdn);
            return DirectoryManager.getObjectInstance(ctx, name, this,
                                                      environment, attrs);
        } catch (NamingException e) {
            cont.setError(this, name);
            throw cont.fillInException(e);
        } catch (Exception e) {
            cont.setError(this, name);
            NamingException ne = new NamingException(
                    "Problem generating object using object factory");
            ne.setRootCause(e);
            throw cont.fillInException(ne);
        }
    }

    public Object c_lookupLink(Name name, Continuation cont)
            throws NamingException {
        return c_lookup(name, cont);
    }

    public NamingEnumeration c_list(Name name, Continuation cont)
            throws NamingException {
        cont.setSuccess();
        try {
            DnsName fqdn = fullyQualify(name);
            NameNode nnode = getNameNode(fqdn);
            DnsContext ctx = new DnsContext(this, fqdn);
            return new NameClassPairEnumeration(ctx, nnode.getChildren());

        } catch (NamingException e) {
            cont.setError(this, name);
            throw cont.fillInException(e);
        }
    }

    public NamingEnumeration c_listBindings(Name name, Continuation cont)
            throws NamingException {
        cont.setSuccess();
        try {
            DnsName fqdn = fullyQualify(name);
            NameNode nnode = getNameNode(fqdn);
            DnsContext ctx = new DnsContext(this, fqdn);
            return new BindingEnumeration(ctx, nnode.getChildren());

        } catch (NamingException e) {
            cont.setError(this, name);
            throw cont.fillInException(e);
        }
    }

    public void c_bind(Name name, Object obj, Continuation cont)
            throws NamingException {
        cont.setError(this, name);
        throw cont.fillInException(
                new OperationNotSupportedException());
    }

    public void c_rebind(Name name, Object obj, Continuation cont)
            throws NamingException {
        cont.setError(this, name);
        throw cont.fillInException(
                new OperationNotSupportedException());
    }

    public void c_unbind(Name name, Continuation cont)
            throws NamingException {
        cont.setError(this, name);
        throw cont.fillInException(
                new OperationNotSupportedException());
    }

    public void c_rename(Name oldname, Name newname, Continuation cont)
            throws NamingException {
        cont.setError(this, oldname);
        throw cont.fillInException(
                new OperationNotSupportedException());
    }

    public Context c_createSubcontext(Name name, Continuation cont)
            throws NamingException {
        cont.setError(this, name);
        throw cont.fillInException(
                new OperationNotSupportedException());
    }

    public void c_destroySubcontext(Name name, Continuation cont)
            throws NamingException {
        cont.setError(this, name);
        throw cont.fillInException(
                new OperationNotSupportedException());
    }

    public NameParser c_getNameParser(Name name, Continuation cont)
            throws NamingException {
        cont.setSuccess();
        return nameParser;
    }


    //---------- Directory operations

    public void c_bind(Name name,
                       Object obj,
                       Attributes attrs,
                       Continuation cont)
            throws NamingException {
        cont.setError(this, name);
        throw cont.fillInException(
                new OperationNotSupportedException());
    }

    public void c_rebind(Name name,
                         Object obj,
                         Attributes attrs,
                         Continuation cont)
            throws NamingException {
        cont.setError(this, name);
        throw cont.fillInException(
                new OperationNotSupportedException());
    }

    public DirContext c_createSubcontext(Name name,
                                         Attributes attrs,
                                         Continuation cont)
            throws NamingException {
        cont.setError(this, name);
        throw cont.fillInException(
                new OperationNotSupportedException());
    }

    public Attributes c_getAttributes(Name name,
                                      String[] attrIds,
                                      Continuation cont)
            throws NamingException {

        cont.setSuccess();
        try {
            DnsName fqdn = fullyQualify(name);
            CT[] cts = attrIdsToClassesAndTypes(attrIds);
            CT ct = getClassAndTypeToQuery(cts);
            ResourceRecords rrs =
                getResolver().query(fqdn, ct.rrclass, ct.rrtype,
                                    recursion, authoritative);
            return rrsToAttrs(rrs, cts);

        } catch (NamingException e) {
            cont.setError(this, name);
            throw cont.fillInException(e);
        }
    }

    public void c_modifyAttributes(Name name,
                                   int mod_op,
                                   Attributes attrs,
                                   Continuation cont)
            throws NamingException {
        cont.setError(this, name);
        throw cont.fillInException(
                new OperationNotSupportedException());
    }

    public void c_modifyAttributes(Name name,
                                   ModificationItem[] mods,
                                   Continuation cont)
            throws NamingException {
        cont.setError(this, name);
        throw cont.fillInException(
                new OperationNotSupportedException());
    }

    public NamingEnumeration c_search(Name name,
                                      Attributes matchingAttributes,
                                      String[] attributesToReturn,
                                      Continuation cont)
            throws NamingException {
        throw new OperationNotSupportedException();
    }

    public NamingEnumeration c_search(Name name,
                                      String filter,
                                      SearchControls cons,
                                      Continuation cont)
            throws NamingException {
        throw new OperationNotSupportedException();
    }

    public NamingEnumeration c_search(Name name,
                                      String filterExpr,
                                      Object[] filterArgs,
                                      SearchControls cons,
                                      Continuation cont)
            throws NamingException {
        throw new OperationNotSupportedException();
    }

    public DirContext c_getSchema(Name name, Continuation cont)
            throws NamingException {
        cont.setError(this, name);
        throw cont.fillInException(
                new OperationNotSupportedException());
    }

    public DirContext c_getSchemaClassDefinition(Name name, Continuation cont)
            throws NamingException {
        cont.setError(this, name);
        throw cont.fillInException(
                new OperationNotSupportedException());
    }


    //---------- Name-related operations

    public String getNameInNamespace() {
        return domain.toString();
    }

    public Name composeName(Name name, Name prefix) throws NamingException {
        Name result;

        // Any name that's not a CompositeName is assumed to be a DNS
        // compound name.  Convert each to a DnsName for syntax checking.
        if (!(prefix instanceof DnsName || prefix instanceof CompositeName)) {
            prefix = (new DnsName()).addAll(prefix);
        }
        if (!(name instanceof DnsName || name instanceof CompositeName)) {
            name = (new DnsName()).addAll(name);
        }

        // Each of prefix and name is now either a DnsName or a CompositeName.

        // If we have two DnsNames, simply join them together.
        if ((prefix instanceof DnsName) && (name instanceof DnsName)) {
            result = (DnsName) (prefix.clone());
            result.addAll(name);
            return new CompositeName().add(result.toString());
        }

        // Wrap compound names in composite names.
        Name prefixC = (prefix instanceof CompositeName)
            ? prefix
            : new CompositeName().add(prefix.toString());
        Name nameC = (name instanceof CompositeName)
            ? name
            : new CompositeName().add(name.toString());
        int prefixLast = prefixC.size() - 1;

        // Let toolkit do the work at namespace boundaries.
        if (nameC.isEmpty() || nameC.get(0).equals("") ||
                prefixC.isEmpty() || prefixC.get(prefixLast).equals("")) {
            return super.composeName(nameC, prefixC);
        }

        result = (prefix == prefixC)
            ? (CompositeName) prefixC.clone()
            : prefixC;                  // prefixC is already a clone
        result.addAll(nameC);

        if (parentIsDns) {
            DnsName dnsComp = (prefix instanceof DnsName)
                           ? (DnsName) prefix.clone()
                           : new DnsName(prefixC.get(prefixLast));
            dnsComp.addAll((name instanceof DnsName)
                           ? name
                           : new DnsName(nameC.get(0)));
            result.remove(prefixLast + 1);
            result.remove(prefixLast);
            result.add(prefixLast, dnsComp.toString());
        }
        return result;
    }


    //---------- Helper methods

    /*
     * Resolver is not created until needed, to allow time for updates
     * to the environment.
     */
    private synchronized Resolver getResolver() throws NamingException {
        if (resolver == null) {
            resolver = new Resolver(servers, timeout, retries);
        }
        return resolver;
    }

    /*
     * Returns the fully-qualified domain name of a name given
     * relative to this context.  Result includes a root label (an
     * empty component at position 0).
     */
    DnsName fullyQualify(Name name) throws NamingException {
        if (name.isEmpty()) {
            return domain;
        }
        DnsName dnsName = (name instanceof CompositeName)
            ? new DnsName(name.get(0))                  // parse name
            : (DnsName) (new DnsName()).addAll(name);   // clone & check syntax

        if (dnsName.hasRootLabel()) {
            // Be overly generous and allow root label if we're in root domain.
            if (domain.size() == 1) {
                return dnsName;
            } else {
                throw new InvalidNameException(
                       "DNS name " + dnsName + " not relative to " + domain);
            }
        }
        return (DnsName) dnsName.addAll(0, domain);
    }

    /*
     * Converts resource records to an attribute set.  Only resource
     * records in the answer section are used, and only those that
     * match the classes and types in cts (see classAndTypeMatch()
     * for matching rules).
     */
    private static Attributes rrsToAttrs(ResourceRecords rrs, CT[] cts) {

        BasicAttributes attrs = new BasicAttributes(true);

        for (int i = 0; i < rrs.answer.size(); i++) {
            ResourceRecord rr = (ResourceRecord) rrs.answer.elementAt(i);
            int rrtype  = rr.getType();
            int rrclass = rr.getRrclass();

            if (!classAndTypeMatch(rrclass, rrtype, cts)) {
                continue;
            }

            String attrId = toAttrId(rrclass, rrtype);
            Attribute attr = attrs.get(attrId);
            if (attr == null) {
                attr = new BasicAttribute(attrId);
                attrs.put(attr);
            }
            attr.add(rr.getRdata());
        }
        return attrs;
    }

    /*
     * Returns true if rrclass and rrtype match some element of cts.
     * A match occurs if corresponding classes and types are equal,
     * or if the array value is ANY.  If cts is null, then any class
     * and type match.
     */
    private static boolean classAndTypeMatch(int rrclass, int rrtype,
                                             CT[] cts) {
        if (cts == null) {
            return true;
        }
        for (int i = 0; i < cts.length; i++) {
            CT ct = cts[i];
            boolean classMatch = (ct.rrclass == ANY) ||
                                 (ct.rrclass == rrclass);
            boolean typeMatch  = (ct.rrtype == ANY) ||
                                 (ct.rrtype == rrtype);
            if (classMatch && typeMatch) {
                return true;
            }
        }
        return false;
    }

    /*
     * Returns the attribute ID for a resource record given its class
     * and type.  If the record is in the internet class, the
     * corresponding attribute ID is the record's type name (or the
     * integer type value if the name is not known).  If the record is
     * not in the internet class, the class name (or integer class
     * value) is prepended to the attribute ID, separated by a space.
     *
     * A class or type value of ANY represents an indeterminate class
     * or type, and is represented within the attribute ID by "*".
     * For example, the attribute ID "IN *" represents
     * any type in the internet class, and "* NS" represents an NS
     * record of any class.
     */
    private static String toAttrId(int rrclass, int rrtype) {
        String attrId = ResourceRecord.getTypeName(rrtype);
        if (rrclass != ResourceRecord.CLASS_INTERNET) {
            attrId = ResourceRecord.getRrclassName(rrclass) + " " + attrId;
        }
        return attrId;
    }

    /*
     * Returns the class and type values corresponding to an attribute
     * ID.  An indeterminate class or type is represented by ANY.  See
     * toAttrId() for the format of attribute IDs.
     *
     * @throws InvalidAttributeIdentifierException
     *          if class or type is unknown
     */
    private static CT fromAttrId(String attrId)
            throws InvalidAttributeIdentifierException {

        if (attrId.equals("")) {
            throw new InvalidAttributeIdentifierException(
                    "Attribute ID cannot be empty");
        }
        int rrclass;
        int rrtype;
        int space = attrId.indexOf(' ');

        // class
        if (space < 0) {
            rrclass = ResourceRecord.CLASS_INTERNET;
        } else {
            String className = attrId.substring(0, space);
            rrclass = ResourceRecord.getRrclass(className);
            if (rrclass < 0) {
                throw new InvalidAttributeIdentifierException(
                        "Unknown resource record class '" + className + '\'');
            }
        }

        // type
        String typeName = attrId.substring(space + 1);
        rrtype = ResourceRecord.getType(typeName);
        if (rrtype < 0) {
            throw new InvalidAttributeIdentifierException(
                    "Unknown resource record type '" + typeName + '\'');
        }

        return new CT(rrclass, rrtype);
    }

    /*
     * Returns an array of the classes and types corresponding to a
     * set of attribute IDs.  See toAttrId() for the format of
     * attribute IDs, and classAndTypeMatch() for the format of the
     * array returned.
     */
    private static CT[] attrIdsToClassesAndTypes(String[] attrIds)
            throws InvalidAttributeIdentifierException {
        if (attrIds == null) {
            return null;
        }
        CT[] cts = new CT[attrIds.length];

        for (int i = 0; i < attrIds.length; i++) {
            cts[i] = fromAttrId(attrIds[i]);
        }
        return cts;
    }

    /*
     * Returns the most restrictive resource record class and type
     * that may be used to query for records matching cts.
     * See classAndTypeMatch() for matching rules.
     */
    private static CT getClassAndTypeToQuery(CT[] cts) {
        int rrclass;
        int rrtype;

        if (cts == null) {
            // Query all records.
            rrclass = ANY;
            rrtype  = ANY;
        } else if (cts.length == 0) {
            // No records are requested, but we need to ask for something.
            rrclass = ResourceRecord.CLASS_INTERNET;
            rrtype  = ANY;
        } else {
            rrclass = cts[0].rrclass;
            rrtype  = cts[0].rrtype;
            for (int i = 1; i < cts.length; i++) {
                if (rrclass != cts[i].rrclass) {
                    rrclass = ANY;
                }
                if (rrtype != cts[i].rrtype) {
                    rrtype = ANY;
                }
            }
        }
        return new CT(rrclass, rrtype);
    }


    //---------- Support for list operations

    /*
     * Synchronization notes:
     *
     * Any access to zoneTree that walks the tree, whether it modifies
     * the tree or not, is synchronized on zoneTree.
     * [%%% Note:  a read/write lock would allow increased concurrency.]
     * The depth of a ZoneNode can thereafter be accessed without
     * further synchronization.  Access to other fields and methods
     * should be synchronized on the node itself.
     *
     * A zone's contents is a NameNode tree that, once created, is never
     * modified.  The only synchronization needed is to ensure that it
     * gets flushed into shared memory after being created, which is
     * accomplished by ZoneNode.populate().  The contents are accessed
     * via a soft reference, so a ZoneNode may be seen to be populated
     * one moment and unpopulated the next.
     */

    /*
     * Returns the node in the zone tree corresponding to a
     * fully-qualified domain name.  If the desired portion of the
     * tree has not yet been populated or has been outdated, a zone
     * transfer is done to populate the tree.
     */
    private NameNode getNameNode(DnsName fqdn) throws NamingException {
        dprint("getNameNode(" + fqdn + ")");

        // Find deepest related zone in zone tree.
        ZoneNode znode;
        DnsName zone;
        synchronized (zoneTree) {
            znode = zoneTree.getDeepestPopulated(fqdn);
        }
        dprint("Deepest related zone in zone tree: " +
               ((znode != null) ? znode.getLabel() : "[none]"));

        NameNode topOfZone;
        NameNode nnode;

        if (znode != null) {
            synchronized (znode) {
                topOfZone = znode.getContents();
            }
            // If fqdn is in znode's zone, is not at a zone cut, and
            // is current, we're done.
            if (topOfZone != null) {
                nnode = topOfZone.get(fqdn, znode.depth() + 1); // +1 for root

                if ((nnode != null) && !nnode.isZoneCut()) {
                    dprint("Found node " + fqdn + " in zone tree");
                    zone = (DnsName)
                        fqdn.getPrefix(znode.depth() + 1);      // +1 for root
                    boolean current = isZoneCurrent(znode, zone);
                    boolean restart = false;

                    synchronized (znode) {
                        if (topOfZone != znode.getContents()) {
                            // Zone was modified while we were examining it.
                            // All bets are off.
                            restart = true;
                        } else if (!current) {
                            znode.depopulate();
                        } else {
                            return nnode;                       // cache hit!
                        }
                    }
                    dprint("Zone not current; discarding node");
                    if (restart) {
                        return getNameNode(fqdn);
                    }
                }
            }
        }

        // Cache miss...  do it the expensive way.
        dprint("Adding node " + fqdn + " to zone tree");

        // Find fqdn's zone and add it to the tree.
        zone = getResolver().findZoneName(fqdn, ResourceRecord.CLASS_INTERNET,
                                          recursion);
        dprint("Node's zone is " + zone);
        synchronized (zoneTree) {
            znode = (ZoneNode) zoneTree.add(zone, 1);   // "1" to skip root
        }

        // If znode is now populated we know -- because the first half of
        // getNodeName() didn't find it -- that it was populated by another
        // thread during this method call.  Assume then that it's current.

        synchronized (znode) {
            topOfZone = znode.isPopulated()
                ? znode.getContents()
                : populateZone(znode, zone);
        }
        // Desired node should now be in znode's populated zone.  Find it.
        nnode = topOfZone.get(fqdn, zone.size());
        if (nnode == null) {
            throw new ConfigurationException(
                    "DNS error: node not found in its own zone");
        }
        dprint("Found node in newly-populated zone");
        return nnode;
    }

    /*
     * Does a zone transfer to [re]populate a zone in the zone tree.
     * Returns the zone's new contents.
     */
    private NameNode populateZone(ZoneNode znode, DnsName zone)
            throws NamingException {
        dprint("Populating zone " + zone);
        // assert Thread.holdsLock(znode);
        ResourceRecords rrs =
            getResolver().queryZone(zone,
                                    ResourceRecord.CLASS_INTERNET, recursion);
        dprint("zone xfer complete: " + rrs.answer.size() + " records");
        return znode.populate(zone, rrs);
    }

    /*
     * Determine if a ZoneNode's data is current.
     * We base this on a comparison between the cached serial
     * number and the latest SOA record.
     *
     * If there is no SOA record, znode is not (or is no longer) a zone:
     * depopulate znode and return false.
     *
     * Since this method may perform a network operation, it is best
     * to call it with znode unlocked.  Caller must then note that the
     * result may be outdated by the time this method returns.
     */
    private boolean isZoneCurrent(ZoneNode znode, DnsName zone)
            throws NamingException {
        // former version:  return !znode.isExpired();

        if (!znode.isPopulated()) {
            return false;
        }
        ResourceRecord soa =
            getResolver().findSoa(zone, ResourceRecord.CLASS_INTERNET,
                                  recursion);
        synchronized (znode) {
            if (soa == null) {
                znode.depopulate();
            }
            return (znode.isPopulated() &&
                    znode.compareSerialNumberTo(soa) >= 0);
        }
    }


    //---------- Debugging

    private static final boolean debug = false;

    private static final void dprint(String msg) {
        if (debug) {
            System.err.println("** " + msg);
        }
    }
}


//----------

/*
 * A pairing of a resource record class and a resource record type.
 * A value of ANY in either field represents an indeterminate value.
 */
class CT {
    int rrclass;
    int rrtype;

    CT(int rrclass, int rrtype) {
        this.rrclass = rrclass;
        this.rrtype = rrtype;
    }
}


//----------

/*
 * An enumeration of name/classname pairs.
 *
 * Nodes that have children or that are zone cuts are returned with
 * classname DirContext.  Other nodes are returned with classname
 * Object even though they are DirContexts as well, since this might
 * make the namespace easier to browse.
 */
class NameClassPairEnumeration implements NamingEnumeration {

    protected Enumeration nodes;    // nodes to be enumerated, or null if none
    protected DnsContext ctx;       // context being enumerated

    NameClassPairEnumeration(DnsContext ctx, Hashtable nodes) {
        this.ctx = ctx;
        this.nodes = (nodes != null)
            ? nodes.elements()
            : null;
    }

    /*
     * ctx will be set to null when no longer needed by the enumeration.
     */
    public void close() {
        nodes = null;
        ctx = null;
    }

    public boolean hasMore() {
        boolean more = ((nodes != null) && nodes.hasMoreElements());
        if (!more) {
            close();
        }
        return more;
    }

    public Object next() throws NamingException {
        if (!hasMore()) {
            throw new java.util.NoSuchElementException();
        }
        NameNode nnode = (NameNode) nodes.nextElement();
        String className = (nnode.isZoneCut() ||
                            (nnode.getChildren() != null))
            ? "javax.naming.directory.DirContext"
            : "java.lang.Object";

        String label = nnode.getLabel();
        Name compName = (new DnsName()).add(label);
        Name cname = (new CompositeName()).add(compName.toString());

        NameClassPair ncp = new NameClassPair(cname.toString(), className);
        ncp.setNameInNamespace(ctx.fullyQualify(cname).toString());
        return ncp;
    }

    public boolean hasMoreElements() {
        return hasMore();
    }

    public Object nextElement() {
        try {
            return next();
        } catch (NamingException e) {
            throw (new java.util.NoSuchElementException(
                    "javax.naming.NamingException was thrown: " +
                    e.getMessage()));
        }
    }
}

/*
 * An enumeration of Bindings.
 */
class BindingEnumeration extends NameClassPairEnumeration {

    BindingEnumeration(DnsContext ctx, Hashtable nodes) {
        super(ctx, nodes);
    }

    // Finalizer not needed since it's safe to leave ctx unclosed.
//  protected void finalize() {
//      close();
//  }

    public Object next() throws NamingException {
        if (!hasMore()) {
            throw (new java.util.NoSuchElementException());
        }
        NameNode nnode = (NameNode) nodes.nextElement();

        String label = nnode.getLabel();
        Name compName = (new DnsName()).add(label);
        String compNameStr = compName.toString();
        Name cname = (new CompositeName()).add(compNameStr);
        String cnameStr = cname.toString();

        DnsName fqdn = ctx.fullyQualify(compName);

        // Clone ctx to create the child context.
        DnsContext child = new DnsContext(ctx, fqdn);

        try {
            Object obj = DirectoryManager.getObjectInstance(
                    child, cname, ctx, child.environment, null);
            Binding binding = new Binding(cnameStr, obj);
            binding.setNameInNamespace(ctx.fullyQualify(cname).toString());
            return binding;
        } catch (Exception e) {
            NamingException ne = new NamingException(
                    "Problem generating object using object factory");
            ne.setRootCause(e);
            throw ne;
        }
    }
}
