/*
 * Copyright (c) 1999, 2005, 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.ldap;

import javax.naming.*;
import javax.naming.directory.*;
import javax.naming.spi.*;
import javax.naming.event.*;
import javax.naming.ldap.*;
import javax.naming.ldap.LdapName;
import javax.naming.ldap.Rdn;

import java.util.Vector;
import java.util.Hashtable;
import java.util.List;
import java.util.StringTokenizer;
import java.util.Enumeration;

import java.io.IOException;
import java.io.OutputStream;

import com.sun.jndi.toolkit.ctx.*;
import com.sun.jndi.toolkit.dir.HierMemDirCtx;
import com.sun.jndi.toolkit.dir.SearchFilter;
import com.sun.jndi.ldap.ext.StartTlsResponseImpl;

/**
 * The LDAP context implementation.
 *
 * Implementation is not thread-safe. Caller must sync as per JNDI spec.
 * Members that are used directly or indirectly by internal worker threads
 * (Connection, EventQueue, NamingEventNotifier) must be thread-safe.
 * Connection - calls LdapClient.processUnsolicited(), which in turn calls
 *   LdapCtx.convertControls() and LdapCtx.fireUnsolicited().
 *   convertControls() - no sync; reads envprops and 'this'
 *   fireUnsolicited() - sync on eventSupport for all references to 'unsolicited'
 *      (even those in other methods);  don't sync on LdapCtx in case caller
 *      is already sync'ing on it - this would prevent Unsol events from firing
 *      and the Connection thread to block (thus preventing any other data
 *      from being read from the connection)
 *      References to 'eventSupport' need not be sync'ed because these
 *      methods can only be called after eventSupport has been set first
 *      (via addNamingListener()).
 * EventQueue - no direct or indirect calls to LdapCtx
 * NamingEventNotifier - calls newInstance() to get instance for run() to use;
 *      no sync needed for methods invoked on new instance;
 *
 * LdapAttribute links to LdapCtx in order to process getAttributeDefinition()
 * and getAttributeSyntaxDefinition() calls. It invokes LdapCtx.getSchema(),
 * which uses schemaTrees (a Hashtable - already sync). Potential conflict
 * of duplicating construction of tree for same subschemasubentry
 * but no inconsistency problems.
 *
 * NamingEnumerations link to LdapCtx for the following:
 * 1. increment/decrement enum count so that ctx doesn't close the
 *    underlying connection
 * 2. LdapClient handle to get next batch of results
 * 3. Sets LdapCtx's response controls
 * 4. Process return code
 * 5. For narrowing response controls (using ctx's factories)
 * Since processing of NamingEnumeration by client is treated the same as method
 * invocation on LdapCtx, caller is responsible for locking.
 *
 * @author Vincent Ryan
 * @author Rosanna Lee
 */

final public class LdapCtx extends ComponentDirContext
    implements EventDirContext, LdapContext {

    /*
     * Used to store arguments to the search method.
     */
    final static class SearchArgs {
        Name name;
        String filter;
        SearchControls cons;
        String[] reqAttrs; // those attributes originally requested

        SearchArgs(Name name, String filter, SearchControls cons, String[] ra) {
            this.name = name;
            this.filter = filter;
            this.cons = cons;
            this.reqAttrs = ra;
        }
    }

    private static final boolean debug = false;

    private static final boolean HARD_CLOSE = true;
    private static final boolean SOFT_CLOSE = false;

    // -----------------  Constants  -----------------

    public static final int DEFAULT_PORT = 389;
    public static final int DEFAULT_SSL_PORT = 636;
    public static final String DEFAULT_HOST = "localhost";

    private static final boolean DEFAULT_DELETE_RDN = true;
    private static final boolean DEFAULT_TYPES_ONLY = false;
    private static final int DEFAULT_DEREF_ALIASES = 3; // always deref
    private static final int DEFAULT_LDAP_VERSION = LdapClient.LDAP_VERSION3_VERSION2;
    private static final int DEFAULT_BATCH_SIZE = 1;
    private static final int DEFAULT_REFERRAL_MODE = LdapClient.LDAP_REF_IGNORE;
    private static final char DEFAULT_REF_SEPARATOR = '#';

        // Used by LdapPoolManager
    static final String DEFAULT_SSL_FACTORY =
        "javax.net.ssl.SSLSocketFactory";       // use Sun's SSL
    private static final int DEFAULT_REFERRAL_LIMIT = 10;
    private static final String STARTTLS_REQ_OID = "1.3.6.1.4.1.1466.20037";

    // schema operational and user attributes
    private static final String[] SCHEMA_ATTRIBUTES =
        { "objectClasses", "attributeTypes", "matchingRules", "ldapSyntaxes" };

    // --------------- Environment property names ----------

    // LDAP protocol version: "2", "3"
    private static final String VERSION = "java.naming.ldap.version";

    // Binary-valued attributes. Space separated string of attribute names.
    private static final String BINARY_ATTRIBUTES =
                                        "java.naming.ldap.attributes.binary";

    // Delete old RDN during modifyDN: "true", "false"
    private static final String DELETE_RDN = "java.naming.ldap.deleteRDN";

    // De-reference aliases: "never", "searching", "finding", "always"
    private static final String DEREF_ALIASES = "java.naming.ldap.derefAliases";

    // Return only attribute types (no values)
    private static final String TYPES_ONLY = "java.naming.ldap.typesOnly";

    // Separator character for encoding Reference's RefAddrs; default is '#'
    private static final String REF_SEPARATOR = "java.naming.ldap.ref.separator";

    // Socket factory
    private static final String SOCKET_FACTORY = "java.naming.ldap.factory.socket";

    // Bind Controls (used by LdapReferralException)
    static final String BIND_CONTROLS = "java.naming.ldap.control.connect";

    private static final String REFERRAL_LIMIT =
        "java.naming.ldap.referral.limit";

    // trace BER (java.io.OutputStream)
    private static final String TRACE_BER = "com.sun.jndi.ldap.trace.ber";

    // Get around Netscape Schema Bugs
    private static final String NETSCAPE_SCHEMA_BUG =
        "com.sun.jndi.ldap.netscape.schemaBugs";
    // deprecated
    private static final String OLD_NETSCAPE_SCHEMA_BUG =
        "com.sun.naming.netscape.schemaBugs";   // for backward compatability

    // Timeout for socket connect
    private static final String CONNECT_TIMEOUT =
        "com.sun.jndi.ldap.connect.timeout";

     // Timeout for reading responses
    private static final String READ_TIMEOUT =
        "com.sun.jndi.ldap.read.timeout";

    // Environment property for connection pooling
    private static final String ENABLE_POOL = "com.sun.jndi.ldap.connect.pool";

    // Environment property for the domain name (derived from this context's DN)
    private static final String DOMAIN_NAME = "com.sun.jndi.ldap.domainname";

    // ----------------- Fields that don't change -----------------------
    private static final NameParser parser = new LdapNameParser();

    // controls that Provider needs
    private static final ControlFactory myResponseControlFactory =
        new DefaultResponseControlFactory();
    private static final Control manageReferralControl =
        new ManageReferralControl(false);

    private static final HierMemDirCtx EMPTY_SCHEMA = new HierMemDirCtx();
    static {
        EMPTY_SCHEMA.setReadOnly(
            new SchemaViolationException("Cannot update schema object"));
    }

    // ------------ Package private instance variables ----------------
    // Cannot be private; used by enums

        // ------- Inherited by derived context instances

    int port_number;                    // port number of server
    String hostname = null;             // host name of server (no brackets
                                        //   for IPv6 literals)
    LdapClient clnt = null;             // connection handle
    Hashtable envprops = null;          // environment properties of context
    int handleReferrals = DEFAULT_REFERRAL_MODE; // how referral is handled
    boolean hasLdapsScheme = false;     // true if the context was created
                                        //  using an LDAPS URL.

        // ------- Not inherited by derived context instances

    String currentDN;                   // DN of this context
    Name currentParsedDN;               // DN of this context
    Vector respCtls = null;             // Response controls read
    Control[] reqCtls = null;           // Controls to be sent with each request


    // ------------- Private instance variables ------------------------

        // ------- Inherited by derived context instances

    private OutputStream trace = null;  // output stream for BER debug output
    private boolean netscapeSchemaBug = false;       // workaround
    private Control[] bindCtls = null;  // Controls to be sent with LDAP "bind"
    private int referralHopLimit = DEFAULT_REFERRAL_LIMIT;  // max referral
    private Hashtable schemaTrees = null; // schema root of this context
    private int batchSize = DEFAULT_BATCH_SIZE;      // batch size for search results
    private boolean deleteRDN = DEFAULT_DELETE_RDN;  // delete the old RDN when modifying DN
    private boolean typesOnly = DEFAULT_TYPES_ONLY;  // return attribute types (no values)
    private int derefAliases = DEFAULT_DEREF_ALIASES;// de-reference alias entries during searching
    private char addrEncodingSeparator = DEFAULT_REF_SEPARATOR;  // encoding RefAddr

    private Hashtable binaryAttrs = null;    // attr values returned as byte[]
    private int connectTimeout = -1;         // no timeout value
    private int readTimeout = -1;            // no timeout value
    private boolean useSsl = false;          // true if SSL protocol is active
    private boolean useDefaultPortNumber = false; // no port number was supplied

        // ------- Not inherited by derived context instances

    // True if this context was created by another LdapCtx.
    private boolean parentIsLdapCtx = false; // see composeName()

    private int hopCount = 1;                // current referral hop count
    private String url = null;               // URL of context; see getURL()
    private EventSupport eventSupport;       // Event support helper for this ctx
    private boolean unsolicited = false;     // if there unsolicited listeners
    private boolean sharable = true;         // can share connection with other ctx

    // -------------- Constructors  -----------------------------------

    public LdapCtx(String dn, String host, int port_number, Hashtable props,
            boolean useSsl) throws NamingException {

        this.useSsl = this.hasLdapsScheme = useSsl;

        if (props != null) {
            envprops = (Hashtable) props.clone();

            // SSL env prop overrides the useSsl argument
            if ("ssl".equals(envprops.get(Context.SECURITY_PROTOCOL))) {
                this.useSsl = true;
            }

            // %%% These are only examined when the context is created
            // %%% because they are only for debugging or workaround purposes.
            trace = (OutputStream)envprops.get(TRACE_BER);

            if (props.get(NETSCAPE_SCHEMA_BUG) != null ||
                props.get(OLD_NETSCAPE_SCHEMA_BUG) != null) {
                netscapeSchemaBug = true;
            }
        }

        currentDN = (dn != null) ? dn : "";
        currentParsedDN = parser.parse(currentDN);

        hostname = (host != null && host.length() > 0) ? host : DEFAULT_HOST;
        if (hostname.charAt(0) == '[') {
            hostname = hostname.substring(1, hostname.length() - 1);
        }

        if (port_number > 0) {
            this.port_number = port_number;
        } else {
            this.port_number = this.useSsl ? DEFAULT_SSL_PORT : DEFAULT_PORT;
            this.useDefaultPortNumber = true;
        }

        schemaTrees = new Hashtable(11, 0.75f);
        initEnv();
        try {
            connect(false);
        } catch (NamingException e) {
            try {
                close();
            } catch (Exception e2) {
                // Nothing
            }
            throw e;
        }
    }

    LdapCtx(LdapCtx existing, String newDN) throws NamingException {
        useSsl = existing.useSsl;
        hasLdapsScheme = existing.hasLdapsScheme;
        useDefaultPortNumber = existing.useDefaultPortNumber;

        hostname = existing.hostname;
        port_number = existing.port_number;
        currentDN = newDN;
        if (existing.currentDN == currentDN) {
            currentParsedDN = existing.currentParsedDN;
        } else {
            currentParsedDN = parser.parse(currentDN);
        }

        envprops = existing.envprops;
        schemaTrees = existing.schemaTrees;

        clnt = existing.clnt;
        clnt.incRefCount();

        parentIsLdapCtx = ((newDN == null || newDN.equals(existing.currentDN))
                           ? existing.parentIsLdapCtx
                           : true);

        // inherit these debugging/workaround flags
        trace = existing.trace;
        netscapeSchemaBug = existing.netscapeSchemaBug;

        initEnv();
    }

    public LdapContext newInstance(Control[] reqCtls) throws NamingException {

        LdapContext clone = new LdapCtx(this, currentDN);

        // Connection controls are inherited from environment

        // Set clone's request controls
        // setRequestControls() will clone reqCtls
        clone.setRequestControls(reqCtls);
        return clone;
    }

    // --------------- Namespace Updates ---------------------
    // -- bind/rebind/unbind
    // -- rename
    // -- createSubcontext/destroySubcontext

    protected void c_bind(Name name, Object obj, Continuation cont)
            throws NamingException {
        c_bind(name, obj, null, cont);
    }

    /*
     * attrs == null
     *      if obj is DirContext, attrs = obj.getAttributes()
     * if attrs == null && obj == null
     *      disallow (cannot determine objectclass to use)
     * if obj == null
     *      just create entry using attrs
     * else
     *      objAttrs = create attributes for representing obj
     *      attrs += objAttrs
     *      create entry using attrs
     */
    protected void c_bind(Name name, Object obj, Attributes attrs,
                          Continuation cont)
            throws NamingException {

        cont.setError(this, name);

        Attributes inputAttrs = attrs; // Attributes supplied by caller
        try {
            ensureOpen();

            if (obj == null) {
                if (attrs == null) {
                    throw new IllegalArgumentException(
                        "cannot bind null object with no attributes");
                }
            } else {
                attrs = Obj.determineBindAttrs(addrEncodingSeparator, obj, attrs,
                    false, name, this, envprops); // not cloned
            }

            String newDN = fullyQualifiedName(name);
            attrs = addRdnAttributes(newDN, attrs, inputAttrs != attrs);
            LdapEntry entry = new LdapEntry(newDN, attrs);

            LdapResult answer = clnt.add(entry, reqCtls);
            respCtls = answer.resControls; // retrieve response controls

            if (answer.status != LdapClient.LDAP_SUCCESS) {
                processReturnCode(answer, name);
            }

        } catch (LdapReferralException e) {
            if (handleReferrals == LdapClient.LDAP_REF_THROW)
                throw cont.fillInException(e);

            // process the referrals sequentially
            while (true) {

                LdapReferralContext refCtx =
                    (LdapReferralContext)e.getReferralContext(envprops, bindCtls);

                // repeat the original operation at the new context
                try {

                    refCtx.bind(name, obj, inputAttrs);
                    return;

                } catch (LdapReferralException re) {
                    e = re;
                    continue;

                } finally {
                    // Make sure we close referral context
                    refCtx.close();
                }
            }

        } catch (IOException e) {
            NamingException e2 = new CommunicationException(e.getMessage());
            e2.setRootCause(e);
            throw cont.fillInException(e2);

        } catch (NamingException e) {
            throw cont.fillInException(e);
        }
    }

    protected void c_rebind(Name name, Object obj, Continuation cont)
            throws NamingException {
        c_rebind(name, obj, null, cont);
    }


    /*
     * attrs == null
     *    if obj is DirContext, attrs = obj.getAttributes().
     * if attrs == null
     *    leave any existing attributes alone
     *    (set attrs = {objectclass=top} if object doesn't exist)
     * else
     *    replace all existing attributes with attrs
     * if obj == null
     *      just create entry using attrs
     * else
     *      objAttrs = create attributes for representing obj
     *      attrs += objAttrs
     *      create entry using attrs
     */
    protected void c_rebind(Name name, Object obj, Attributes attrs,
        Continuation cont) throws NamingException {

        cont.setError(this, name);

        Attributes inputAttrs = attrs;

        try {
            Attributes origAttrs = null;

            // Check if name is bound
            try {
                origAttrs = c_getAttributes(name, null, cont);
            } catch (NameNotFoundException e) {}

            // Name not bound, just add it
            if (origAttrs == null) {
                c_bind(name, obj, attrs, cont);
                return;
            }

            // there's an object there already, need to figure out
            // what to do about its attributes

            if (attrs == null && obj instanceof DirContext) {
                attrs = ((DirContext)obj).getAttributes("");
            }
            Attributes keepAttrs = (Attributes)origAttrs.clone();

            if (attrs == null) {
                // we're not changing any attrs, leave old attributes alone

                // Remove Java-related object classes from objectclass attribute
                Attribute origObjectClass =
                    origAttrs.get(Obj.JAVA_ATTRIBUTES[Obj.OBJECT_CLASS]);

                if (origObjectClass != null) {
                    // clone so that keepAttrs is not affected
                    origObjectClass = (Attribute)origObjectClass.clone();
                    for (int i = 0; i < Obj.JAVA_OBJECT_CLASSES.length; i++) {
                        origObjectClass.remove(Obj.JAVA_OBJECT_CLASSES_LOWER[i]);
                        origObjectClass.remove(Obj.JAVA_OBJECT_CLASSES[i]);
                    }
                    // update;
                    origAttrs.put(origObjectClass);
                }

                // remove all Java-related attributes except objectclass
                for (int i = 1; i < Obj.JAVA_ATTRIBUTES.length; i++) {
                    origAttrs.remove(Obj.JAVA_ATTRIBUTES[i]);
                }

                attrs = origAttrs;
            }
            if (obj != null) {
                attrs =
                    Obj.determineBindAttrs(addrEncodingSeparator, obj, attrs,
                        inputAttrs != attrs, name, this, envprops);
            }

            String newDN = fullyQualifiedName(name);
            // remove entry
            LdapResult answer = clnt.delete(newDN, reqCtls);
            respCtls = answer.resControls; // retrieve response controls

            if (answer.status != LdapClient.LDAP_SUCCESS) {
                processReturnCode(answer, name);
                return;
            }

            Exception addEx = null;
            try {
                attrs = addRdnAttributes(newDN, attrs, inputAttrs != attrs);

                // add it back using updated attrs
                LdapEntry entry = new LdapEntry(newDN, attrs);
                answer = clnt.add(entry, reqCtls);
                if (answer.resControls != null) {
                    respCtls = appendVector(respCtls, answer.resControls);
                }
            } catch (NamingException ae) {
                addEx = ae;
            } catch (IOException ae) {
                addEx = ae;
            }

            if ((addEx != null && !(addEx instanceof LdapReferralException)) ||
                answer.status != LdapClient.LDAP_SUCCESS) {
                // Attempt to restore old entry
                LdapResult answer2 =
                    clnt.add(new LdapEntry(newDN, keepAttrs), reqCtls);
                if (answer2.resControls != null) {
                    respCtls = appendVector(respCtls, answer2.resControls);
                }

                if (addEx == null) {
                    processReturnCode(answer, name);
                }
            }

            // Rethrow exception
            if (addEx instanceof NamingException) {
                throw (NamingException)addEx;
            } else if (addEx instanceof IOException) {
                throw (IOException)addEx;
            }

        } catch (LdapReferralException e) {
            if (handleReferrals == LdapClient.LDAP_REF_THROW)
                throw cont.fillInException(e);

            // process the referrals sequentially
            while (true) {

                LdapReferralContext refCtx =
                    (LdapReferralContext)e.getReferralContext(envprops, bindCtls);

                // repeat the original operation at the new context
                try {

                    refCtx.rebind(name, obj, inputAttrs);
                    return;

                } catch (LdapReferralException re) {
                    e = re;
                    continue;

                } finally {
                    // Make sure we close referral context
                    refCtx.close();
                }
            }

        } catch (IOException e) {
            NamingException e2 = new CommunicationException(e.getMessage());
            e2.setRootCause(e);
            throw cont.fillInException(e2);

        } catch (NamingException e) {
            throw cont.fillInException(e);
        }
    }

    protected void c_unbind(Name name, Continuation cont)
            throws NamingException {
        cont.setError(this, name);

        try {
            ensureOpen();

            String fname = fullyQualifiedName(name);
            LdapResult answer = clnt.delete(fname, reqCtls);
            respCtls = answer.resControls; // retrieve response controls

            adjustDeleteStatus(fname, answer);

            if (answer.status != LdapClient.LDAP_SUCCESS) {
                processReturnCode(answer, name);
            }

        } catch (LdapReferralException e) {
            if (handleReferrals == LdapClient.LDAP_REF_THROW)
                throw cont.fillInException(e);

            // process the referrals sequentially
            while (true) {

                LdapReferralContext refCtx =
                    (LdapReferralContext)e.getReferralContext(envprops, bindCtls);

                // repeat the original operation at the new context
                try {

                    refCtx.unbind(name);
                    return;

                } catch (LdapReferralException re) {
                    e = re;
                    continue;

                } finally {
                    // Make sure we close referral context
                    refCtx.close();
                }
            }

        } catch (IOException e) {
            NamingException e2 = new CommunicationException(e.getMessage());
            e2.setRootCause(e);
            throw cont.fillInException(e2);

        } catch (NamingException e) {
            throw cont.fillInException(e);
        }
    }

    protected void c_rename(Name oldName, Name newName, Continuation cont)
            throws NamingException
    {
        Name oldParsed, newParsed;
        Name oldParent, newParent;
        String newRDN = null;
        String newSuperior = null;

        // assert (oldName instanceOf CompositeName);

        cont.setError(this, oldName);

        try {
            ensureOpen();

            // permit oldName to be empty (for processing referral contexts)
            if (oldName.isEmpty()) {
                oldParent = parser.parse("");
            } else {
                oldParsed = parser.parse(oldName.get(0)); // extract DN & parse
                oldParent = oldParsed.getPrefix(oldParsed.size() - 1);
            }

            if (newName instanceof CompositeName) {
                newParsed = parser.parse(newName.get(0)); // extract DN & parse
            } else {
                newParsed = newName; // CompoundName/LdapName is already parsed
            }
            newParent = newParsed.getPrefix(newParsed.size() - 1);

            if(!oldParent.equals(newParent)) {
                if (!clnt.isLdapv3) {
                    throw new InvalidNameException(
                                  "LDAPv2 doesn't support changing " +
                                  "the parent as a result of a rename");
                } else {
                    newSuperior = fullyQualifiedName(newParent.toString());
                }
            }

            newRDN = newParsed.get(newParsed.size() - 1);

            LdapResult answer = clnt.moddn(fullyQualifiedName(oldName),
                                    newRDN,
                                    deleteRDN,
                                    newSuperior,
                                    reqCtls);
            respCtls = answer.resControls; // retrieve response controls

            if (answer.status != LdapClient.LDAP_SUCCESS) {
                processReturnCode(answer, oldName);
            }

        } catch (LdapReferralException e) {

            // Record the new RDN (for use after the referral is followed).
            e.setNewRdn(newRDN);

            // Cannot continue when a referral has been received and a
            // newSuperior name was supplied (because the newSuperior is
            // relative to a naming context BEFORE the referral is followed).
            if (newSuperior != null) {
                PartialResultException pre = new PartialResultException(
                    "Cannot continue referral processing when newSuperior is " +
                    "nonempty: " + newSuperior);
                pre.setRootCause(cont.fillInException(e));
                throw cont.fillInException(pre);
            }

            if (handleReferrals == LdapClient.LDAP_REF_THROW)
                throw cont.fillInException(e);

            // process the referrals sequentially
            while (true) {

                LdapReferralContext refCtx =
                    (LdapReferralContext)e.getReferralContext(envprops, bindCtls);

                // repeat the original operation at the new context
                try {

                    refCtx.rename(oldName, newName);
                    return;

                } catch (LdapReferralException re) {
                    e = re;
                    continue;

                } finally {
                    // Make sure we close referral context
                    refCtx.close();
                }
            }

        } catch (IOException e) {
            NamingException e2 = new CommunicationException(e.getMessage());
            e2.setRootCause(e);
            throw cont.fillInException(e2);

        } catch (NamingException e) {
            throw cont.fillInException(e);
        }
    }

    protected Context c_createSubcontext(Name name, Continuation cont)
            throws NamingException {
        return c_createSubcontext(name, null, cont);
    }

    protected DirContext c_createSubcontext(Name name, Attributes attrs,
                                            Continuation cont)
            throws NamingException {
        cont.setError(this, name);

        Attributes inputAttrs = attrs;
        try {
            ensureOpen();
            if (attrs == null) {
                  // add structural objectclass; name needs to have "cn"
                  Attribute oc = new BasicAttribute(
                      Obj.JAVA_ATTRIBUTES[Obj.OBJECT_CLASS],
                      Obj.JAVA_OBJECT_CLASSES[Obj.STRUCTURAL]);
                  oc.add("top");
                  attrs = new BasicAttributes(true); // case ignore
                  attrs.put(oc);
            }
            String newDN = fullyQualifiedName(name);
            attrs = addRdnAttributes(newDN, attrs, inputAttrs != attrs);

            LdapEntry entry = new LdapEntry(newDN, attrs);

            LdapResult answer = clnt.add(entry, reqCtls);
            respCtls = answer.resControls; // retrieve response controls

            if (answer.status != LdapClient.LDAP_SUCCESS) {
                processReturnCode(answer, name);
                return null;
            }

            // creation successful, get back live object
            return new LdapCtx(this, newDN);

        } catch (LdapReferralException e) {
            if (handleReferrals == LdapClient.LDAP_REF_THROW)
                throw cont.fillInException(e);

            // process the referrals sequentially
            while (true) {

                LdapReferralContext refCtx =
                    (LdapReferralContext)e.getReferralContext(envprops, bindCtls);

                // repeat the original operation at the new context
                try {

                    return refCtx.createSubcontext(name, inputAttrs);

                } catch (LdapReferralException re) {
                    e = re;
                    continue;

                } finally {
                    // Make sure we close referral context
                    refCtx.close();
                }
            }

        } catch (IOException e) {
            NamingException e2 = new CommunicationException(e.getMessage());
            e2.setRootCause(e);
            throw cont.fillInException(e2);

        } catch (NamingException e) {
            throw cont.fillInException(e);
        }
    }

    protected void c_destroySubcontext(Name name, Continuation cont)
        throws NamingException {
        cont.setError(this, name);

        try {
            ensureOpen();

            String fname = fullyQualifiedName(name);
            LdapResult answer = clnt.delete(fname, reqCtls);
            respCtls = answer.resControls; // retrieve response controls

            adjustDeleteStatus(fname, answer);

            if (answer.status != LdapClient.LDAP_SUCCESS) {
                processReturnCode(answer, name);
            }

        } catch (LdapReferralException e) {
            if (handleReferrals == LdapClient.LDAP_REF_THROW)
                throw cont.fillInException(e);

            // process the referrals sequentially
            while (true) {

                LdapReferralContext refCtx =
                    (LdapReferralContext)e.getReferralContext(envprops, bindCtls);

                // repeat the original operation at the new context
                try {

                    refCtx.destroySubcontext(name);
                    return;
                } catch (LdapReferralException re) {
                    e = re;
                    continue;
                } finally {
                    // Make sure we close referral context
                    refCtx.close();
                }
            }
        } catch (IOException e) {
            NamingException e2 = new CommunicationException(e.getMessage());
            e2.setRootCause(e);
            throw cont.fillInException(e2);
        } catch (NamingException e) {
            throw cont.fillInException(e);
        }
    }

    /**
     * Adds attributes from RDN to attrs if not already present.
     * Note that if attrs already contains an attribute by the same name,
     * or if the distinguished name is empty, then leave attrs unchanged.
     *
     * @param dn The non-null DN of the entry to add
     * @param attrs The non-null attributes of entry to add
     * @param directUpdate Whether attrs can be updated directly
     * @returns Non-null attributes with attributes from the RDN added
     */
    private static Attributes addRdnAttributes(String dn, Attributes attrs,
        boolean directUpdate) throws NamingException {

            // Handle the empty name
            if (dn.equals("")) {
                return attrs;
            }

            // Parse string name into list of RDNs
            //List<Rdn> rdnList = (new LdapName(dn)).rdns();
            List rdnList = (new LdapName(dn)).getRdns();

            // Get leaf RDN
            //Rdn rdn = rdnList.get(rdnList.size() - 1);
            Rdn rdn = (Rdn) rdnList.get(rdnList.size() - 1);
            Attributes nameAttrs = rdn.toAttributes();

            // Add attributes of RDN to attrs if not already there
            NamingEnumeration enum_ = nameAttrs.getAll();
            Attribute nameAttr;
            while (enum_.hasMore()) {
                nameAttr = (Attribute) enum_.next();

                // If attrs already has the attribute, don't change or add to it
                if (attrs.get(nameAttr.getID()) ==  null) {

                    /**
                     * When attrs.isCaseIgnored() is false, attrs.get() will
                     * return null when the case mis-matches for otherwise
                     * equal attrIDs.
                     * As the attrIDs' case is irrelevant for LDAP, ignore
                     * the case of attrIDs even when attrs.isCaseIgnored() is
                     * false. This is done by explicitly comparing the elements in
                     * the enumeration of IDs with their case ignored.
                     */
                    if (!attrs.isCaseIgnored() &&
                            containsIgnoreCase(attrs.getIDs(), nameAttr.getID())) {
                        continue;
                    }

                    if (!directUpdate) {
                        attrs = (Attributes)attrs.clone();
                        directUpdate = true;
                    }
                    attrs.put(nameAttr);
                }
            }

            return attrs;
    }


    private static boolean containsIgnoreCase(NamingEnumeration enumStr,
                                String str) throws NamingException {
        String strEntry;

        while (enumStr.hasMore()) {
             strEntry = (String) enumStr.next();
             if (strEntry.equalsIgnoreCase(str)) {
                return true;
             }
        }
        return false;
    }


    private void adjustDeleteStatus(String fname, LdapResult answer) {
        if (answer.status == LdapClient.LDAP_NO_SUCH_OBJECT &&
            answer.matchedDN != null) {
            try {
                // %%% RL: are there any implications for referrals?

                Name orig = parser.parse(fname);
                Name matched = parser.parse(answer.matchedDN);
                if ((orig.size() - matched.size()) == 1)
                    answer.status = LdapClient.LDAP_SUCCESS;
            } catch (NamingException e) {}
        }
    }

    /*
     * Append the the second Vector onto the first Vector
     * (v2 must be non-null)
     */
    private static Vector appendVector(Vector v1, Vector v2) {
        if (v1 == null) {
            v1 = v2;
        } else {
            for (int i = 0; i < v2.size(); i++) {
                v1.addElement(v2.elementAt(i));
            }
        }
        return v1;
    }

    // ------------- Lookups and Browsing -------------------------
    // lookup/lookupLink
    // list/listBindings

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

    protected Object c_lookup(Name name, Continuation cont)
            throws NamingException {
        cont.setError(this, name);
        Object obj = null;
        Attributes attrs;

        try {
            SearchControls cons = new SearchControls();
            cons.setSearchScope(SearchControls.OBJECT_SCOPE);
            cons.setReturningAttributes(null); // ask for all attributes
            cons.setReturningObjFlag(true); // need values to construct obj

            LdapResult answer = doSearchOnce(name, "(objectClass=*)", cons, true);
            respCtls = answer.resControls; // retrieve response controls

            // should get back 1 SearchResponse and 1 SearchResult

            if (answer.status != LdapClient.LDAP_SUCCESS) {
                processReturnCode(answer, name);
            }

            if (answer.entries == null || answer.entries.size() != 1) {
                // found it but got no attributes
                attrs = new BasicAttributes(LdapClient.caseIgnore);
            } else {
                LdapEntry entry = (LdapEntry)answer.entries.elementAt(0);
                attrs = entry.attributes;

                Vector entryCtls = entry.respCtls; // retrieve entry controls
                if (entryCtls != null) {
                    appendVector(respCtls, entryCtls); // concatenate controls
                }
            }

            if (attrs.get(Obj.JAVA_ATTRIBUTES[Obj.CLASSNAME]) != null) {
                // serialized object or object reference
                obj = Obj.decodeObject(attrs);
            }
            if (obj == null) {
                obj = new LdapCtx(this, fullyQualifiedName(name));
            }
        } catch (LdapReferralException e) {
            if (handleReferrals == LdapClient.LDAP_REF_THROW)
                throw cont.fillInException(e);

            // process the referrals sequentially
            while (true) {

                LdapReferralContext refCtx =
                    (LdapReferralContext)e.getReferralContext(envprops, bindCtls);
                // repeat the original operation at the new context
                try {

                    return refCtx.lookup(name);

                } catch (LdapReferralException re) {
                    e = re;
                    continue;

                } finally {
                    // Make sure we close referral context
                    refCtx.close();
                }
            }

        } catch (NamingException e) {
            throw cont.fillInException(e);
        }

        try {
            return DirectoryManager.getObjectInstance(obj, name,
                this, envprops, attrs);

        } catch (NamingException e) {
            throw cont.fillInException(e);

        } catch (Exception e) {
            NamingException e2 = new NamingException(
                    "problem generating object using object factory");
            e2.setRootCause(e);
            throw cont.fillInException(e2);
        }
    }

    protected NamingEnumeration c_list(Name name, Continuation cont)
            throws NamingException {
        SearchControls cons = new SearchControls();
        String[] classAttrs = new String[2];

        classAttrs[0] = Obj.JAVA_ATTRIBUTES[Obj.OBJECT_CLASS];
        classAttrs[1] = Obj.JAVA_ATTRIBUTES[Obj.CLASSNAME];
        cons.setReturningAttributes(classAttrs);

        // set this flag to override the typesOnly flag
        cons.setReturningObjFlag(true);

        cont.setError(this, name);

        LdapResult answer = null;

        try {
            answer = doSearch(name, "(objectClass=*)", cons, true, true);

            // list result may contain continuation references
            if ((answer.status != LdapClient.LDAP_SUCCESS) ||
                (answer.referrals != null)) {
                processReturnCode(answer, name);
            }

            return new LdapNamingEnumeration(this, answer, name, cont);

        } catch (LdapReferralException e) {
            if (handleReferrals == LdapClient.LDAP_REF_THROW)
                throw cont.fillInException(e);

            // process the referrals sequentially
            while (true) {

                LdapReferralContext refCtx =
                    (LdapReferralContext)e.getReferralContext(envprops, bindCtls);

                // repeat the original operation at the new context
                try {

                    return refCtx.list(name);

                } catch (LdapReferralException re) {
                    e = re;
                    continue;

                } finally {
                    // Make sure we close referral context
                    refCtx.close();
                }
            }

        } catch (LimitExceededException e) {
            LdapNamingEnumeration res =
                new LdapNamingEnumeration(this, answer, name, cont);

            res.setNamingException(
                    (LimitExceededException)cont.fillInException(e));
            return res;

        } catch (PartialResultException e) {
            LdapNamingEnumeration res =
                new LdapNamingEnumeration(this, answer, name, cont);

            res.setNamingException(
                    (PartialResultException)cont.fillInException(e));
            return res;

        } catch (NamingException e) {
            throw cont.fillInException(e);
        }
    }

    protected NamingEnumeration c_listBindings(Name name, Continuation cont)
            throws NamingException {

        SearchControls cons = new SearchControls();
        cons.setReturningAttributes(null); // ask for all attributes
        cons.setReturningObjFlag(true); // need values to construct obj

        cont.setError(this, name);

        LdapResult answer = null;

        try {
            answer = doSearch(name, "(objectClass=*)", cons, true, true);

            // listBindings result may contain continuation references
            if ((answer.status != LdapClient.LDAP_SUCCESS) ||
                (answer.referrals != null)) {
                processReturnCode(answer, name);
            }

            return new LdapBindingEnumeration(this, answer, name, cont);

        } catch (LdapReferralException e) {
            if (handleReferrals == LdapClient.LDAP_REF_THROW)
                throw cont.fillInException(e);

            // process the referrals sequentially
            while (true) {

                LdapReferralContext refCtx =
                    (LdapReferralContext)e.getReferralContext(envprops, bindCtls);

                // repeat the original operation at the new context
                try {

                    return refCtx.listBindings(name);

                } catch (LdapReferralException re) {
                    e = re;
                    continue;

                } finally {
                    // Make sure we close referral context
                    refCtx.close();
                }
            }
        } catch (LimitExceededException e) {
            LdapBindingEnumeration res =
                new LdapBindingEnumeration(this, answer, name, cont);

            res.setNamingException(
                    (LimitExceededException)cont.fillInException(e));
            return res;

        } catch (PartialResultException e) {
            LdapBindingEnumeration res =
                new LdapBindingEnumeration(this, answer, name, cont);

            res.setNamingException(
                    (PartialResultException)cont.fillInException(e));
            return res;

        } catch (NamingException e) {
            throw cont.fillInException(e);
        }
    }

    // --------------- Name-related Methods -----------------------
    // -- getNameParser/getNameInNamespace/composeName

    protected NameParser c_getNameParser(Name name, Continuation cont)
            throws NamingException
    {
        // ignore name, always return same parser
        cont.setSuccess();
        return parser;
    }

    public String getNameInNamespace() {
        return currentDN;
    }

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

        // Handle compound names.  A pair of LdapNames is an easy case.
        if ((name instanceof LdapName) && (prefix instanceof LdapName)) {
            result = (Name)(prefix.clone());
            result.addAll(name);
            return new CompositeName().add(result.toString());
        }
        if (!(name instanceof CompositeName)) {
            name = new CompositeName().add(name.toString());
        }
        if (!(prefix instanceof CompositeName)) {
            prefix = new CompositeName().add(prefix.toString());
        }

        int prefixLast = prefix.size() - 1;

        if (name.isEmpty() || prefix.isEmpty() ||
                name.get(0).equals("") || prefix.get(prefixLast).equals("")) {
            return super.composeName(name, prefix);
        }

        result = (Name)(prefix.clone());
        result.addAll(name);

        if (parentIsLdapCtx) {
            String ldapComp = concatNames(result.get(prefixLast + 1),
                                          result.get(prefixLast));
            result.remove(prefixLast + 1);
            result.remove(prefixLast);
            result.add(prefixLast, ldapComp);
        }
        return result;
    }

    private String fullyQualifiedName(Name rel) {
        return rel.isEmpty()
                ? currentDN
                : fullyQualifiedName(rel.get(0));
    }

    private String fullyQualifiedName(String rel) {
        return (concatNames(rel, currentDN));
    }

    // used by LdapSearchEnumeration
    private static String concatNames(String lesser, String greater) {
        if (lesser == null || lesser.equals("")) {
            return greater;
        } else if (greater == null || greater.equals("")) {
            return lesser;
        } else {
            return (lesser + "," + greater);
        }
    }

   // --------------- Reading and Updating Attributes
   // getAttributes/modifyAttributes

    protected Attributes c_getAttributes(Name name, String[] attrIds,
                                      Continuation cont)
            throws NamingException {
        cont.setError(this, name);

        SearchControls cons = new SearchControls();
        cons.setSearchScope(SearchControls.OBJECT_SCOPE);
        cons.setReturningAttributes(attrIds);

        try {
            LdapResult answer =
                doSearchOnce(name, "(objectClass=*)", cons, true);
            respCtls = answer.resControls; // retrieve response controls

            if (answer.status != LdapClient.LDAP_SUCCESS) {
                processReturnCode(answer, name);
            }

            if (answer.entries == null || answer.entries.size() != 1) {
                return new BasicAttributes(LdapClient.caseIgnore);
            }

            // get attributes from result
            LdapEntry entry = (LdapEntry) answer.entries.elementAt(0);

            Vector entryCtls = entry.respCtls; // retrieve entry controls
            if (entryCtls != null) {
                appendVector(respCtls, entryCtls); // concatenate controls
            }

            // do this so attributes can find their schema
            setParents(entry.attributes, (Name) name.clone());

            return (entry.attributes);

        } catch (LdapReferralException e) {
            if (handleReferrals == LdapClient.LDAP_REF_THROW)
                throw cont.fillInException(e);

            // process the referrals sequentially
            while (true) {

                LdapReferralContext refCtx =
                    (LdapReferralContext)e.getReferralContext(envprops, bindCtls);

                // repeat the original operation at the new context
                try {

                    return refCtx.getAttributes(name, attrIds);

                } catch (LdapReferralException re) {
                    e = re;
                    continue;

                } finally {
                    // Make sure we close referral context
                    refCtx.close();
                }
            }

        } catch (NamingException e) {
            throw cont.fillInException(e);
        }
    }

    protected void c_modifyAttributes(Name name, int mod_op, Attributes attrs,
                                      Continuation cont)
            throws NamingException {

        cont.setError(this, name);

        try {
            ensureOpen();

            if (attrs == null || attrs.size() == 0) {
                return; // nothing to do
            }
            String newDN = fullyQualifiedName(name);
            int jmod_op = convertToLdapModCode(mod_op);

            // construct mod list
            int[] jmods = new int[attrs.size()];
            Attribute[] jattrs = new Attribute[attrs.size()];

            NamingEnumeration ae = attrs.getAll();
            for(int i = 0; i < jmods.length && ae.hasMore(); i++) {
                jmods[i] = jmod_op;
                jattrs[i] = (Attribute)ae.next();
            }

            LdapResult answer = clnt.modify(newDN, jmods, jattrs, reqCtls);
            respCtls = answer.resControls; // retrieve response controls

            if (answer.status != LdapClient.LDAP_SUCCESS) {
                processReturnCode(answer, name);
                return;
            }

        } catch (LdapReferralException e) {
            if (handleReferrals == LdapClient.LDAP_REF_THROW)
                throw cont.fillInException(e);

            // process the referrals sequentially
            while (true) {

                LdapReferralContext refCtx =
                    (LdapReferralContext)e.getReferralContext(envprops, bindCtls);

                // repeat the original operation at the new context
                try {

                    refCtx.modifyAttributes(name, mod_op, attrs);
                    return;

                } catch (LdapReferralException re) {
                    e = re;
                    continue;

                } finally {
                    // Make sure we close referral context
                    refCtx.close();
                }
            }

        } catch (IOException e) {
            NamingException e2 = new CommunicationException(e.getMessage());
            e2.setRootCause(e);
            throw cont.fillInException(e2);

        } catch (NamingException e) {
            throw cont.fillInException(e);
        }
    }

    protected void c_modifyAttributes(Name name, ModificationItem[] mods,
                                      Continuation cont)
            throws NamingException {
        cont.setError(this, name);

        try {
            ensureOpen();

            if (mods == null || mods.length == 0) {
                return; // nothing to do
            }
            String newDN = fullyQualifiedName(name);

            // construct mod list
            int[] jmods = new int[mods.length];
            Attribute[] jattrs = new Attribute[mods.length];
            ModificationItem mod;
            for (int i = 0; i < jmods.length; i++) {
                mod = mods[i];
                jmods[i] = convertToLdapModCode(mod.getModificationOp());
                jattrs[i] = mod.getAttribute();
            }

            LdapResult answer = clnt.modify(newDN, jmods, jattrs, reqCtls);
            respCtls = answer.resControls; // retrieve response controls

            if (answer.status != LdapClient.LDAP_SUCCESS) {
                processReturnCode(answer, name);
            }

        } catch (LdapReferralException e) {
            if (handleReferrals == LdapClient.LDAP_REF_THROW)
                throw cont.fillInException(e);

            // process the referrals sequentially
            while (true) {

                LdapReferralContext refCtx =
                    (LdapReferralContext)e.getReferralContext(envprops, bindCtls);

                // repeat the original operation at the new context
                try {

                    refCtx.modifyAttributes(name, mods);
                    return;

                } catch (LdapReferralException re) {
                    e = re;
                    continue;

                } finally {
                    // Make sure we close referral context
                    refCtx.close();
                }
            }

        } catch (IOException e) {
            NamingException e2 = new CommunicationException(e.getMessage());
            e2.setRootCause(e);
            throw cont.fillInException(e2);

        } catch (NamingException e) {
            throw cont.fillInException(e);
        }
    }

    private static int convertToLdapModCode(int mod_op) {
        switch (mod_op) {
        case DirContext.ADD_ATTRIBUTE:
            return(LdapClient.ADD);

        case DirContext.REPLACE_ATTRIBUTE:
            return (LdapClient.REPLACE);

        case DirContext.REMOVE_ATTRIBUTE:
            return (LdapClient.DELETE);

        default:
            throw new IllegalArgumentException("Invalid modification code");
        }
    }

   // ------------------- Schema -----------------------

    protected DirContext c_getSchema(Name name, Continuation cont)
            throws NamingException {
        cont.setError(this, name);
        try {
            return getSchemaTree(name);

        } catch (NamingException e) {
            throw cont.fillInException(e);
        }
    }

    protected DirContext c_getSchemaClassDefinition(Name name,
                                                    Continuation cont)
            throws NamingException {
        cont.setError(this, name);

        try {
            // retrieve the objectClass attribute from LDAP
            Attribute objectClassAttr = c_getAttributes(name,
                new String[]{"objectclass"}, cont).get("objectclass");
            if (objectClassAttr == null || objectClassAttr.size() == 0) {
                return EMPTY_SCHEMA;
            }

            // retrieve the root of the ObjectClass schema tree
            Context ocSchema = (Context) c_getSchema(name, cont).lookup(
                LdapSchemaParser.OBJECTCLASS_DEFINITION_NAME);

            // create a context to hold the schema objects representing the object
            // classes
            HierMemDirCtx objectClassCtx = new HierMemDirCtx();
            DirContext objectClassDef;
            String objectClassName;
            for (Enumeration objectClasses = objectClassAttr.getAll();
                objectClasses.hasMoreElements(); ) {
                objectClassName = (String)objectClasses.nextElement();
                // %%% Should we fail if not found, or just continue?
                objectClassDef = (DirContext)ocSchema.lookup(objectClassName);
                objectClassCtx.bind(objectClassName, objectClassDef);
            }

            // Make context read-only
            objectClassCtx.setReadOnly(
                new SchemaViolationException("Cannot update schema object"));
            return (DirContext)objectClassCtx;

        } catch (NamingException e) {
            throw cont.fillInException(e);
        }
    }

    /*
     * getSchemaTree first looks to see if we have already built a
     * schema tree for the given entry. If not, it builds a new one and
     * stores it in our private hash table
     */
    private DirContext getSchemaTree(Name name) throws NamingException {
        String subschemasubentry = getSchemaEntry(name, true);

        DirContext schemaTree = (DirContext)schemaTrees.get(subschemasubentry);

        if(schemaTree==null) {
            if(debug){System.err.println("LdapCtx: building new schema tree " + this);}
            schemaTree = buildSchemaTree(subschemasubentry);
            schemaTrees.put(subschemasubentry, schemaTree);
        }

        return schemaTree;
    }

    /*
     * buildSchemaTree builds the schema tree corresponding to the
     * given subschemasubentree
     */
    private DirContext buildSchemaTree(String subschemasubentry)
        throws NamingException {

        // get the schema entry itself
        // DO ask for return object here because we need it to
        // create context. Since asking for all attrs, we won't
        // be transmitting any specific attrIDs (like Java-specific ones).
        SearchControls constraints = new
            SearchControls(SearchControls.OBJECT_SCOPE,
                0, 0, /* count and time limits */
                SCHEMA_ATTRIBUTES /* return schema attrs */,
                true /* return obj */,
                false /*deref link */ );

        Name sse = (new CompositeName()).add(subschemasubentry);
        NamingEnumeration results =
            searchAux(sse, "(objectClass=subschema)", constraints,
            false, true, new Continuation());

        if(!results.hasMore()) {
            throw new OperationNotSupportedException(
                "Cannot get read subschemasubentry: " + subschemasubentry);
        }
        SearchResult result = (SearchResult)results.next();
        results.close();

        Object obj = result.getObject();
        if(!(obj instanceof LdapCtx)) {
            throw new NamingException(
                "Cannot get schema object as DirContext: " + subschemasubentry);
        }

        return LdapSchemaCtx.createSchemaTree(envprops, subschemasubentry,
            (LdapCtx)obj /* schema entry */,
            result.getAttributes() /* schema attributes */,
            netscapeSchemaBug);
   }

    /*
     * getSchemaEntree returns the DN of the subschemasubentree for the
     * given entree. It first looks to see if the given entry has
     * a subschema different from that of the root DIT (by looking for
     * a "subschemasubentry" attribute). If it doesn't find one, it returns
     * the one for the root of the DIT (by looking for the root's
     * "subschemasubentry" attribute).
     *
     * This function is called regardless of the server's version, since
     * an administrator may have setup the server to support client schema
     * queries. If this function trys a serarch on a v2 server that
     * doesn't support schema, one of these two things will happen:
     * 1) It will get an exception when querying the root DSE
     * 2) It will not find a subschemasubentry on the root DSE
     * If either of these things occur and the server is not v3, we
     * throw OperationNotSupported.
     *
     * the relative flag tells whether the given name is relative to this
     * context.
     */
    private String getSchemaEntry(Name name, boolean relative)
        throws NamingException {

        // Asks for operational attribute "subschemasubentry"
        SearchControls constraints = new SearchControls(SearchControls.OBJECT_SCOPE,
            0, 0, /* count and time limits */
            new String[]{"subschemasubentry"} /* attr to return */,
            false /* returning obj */,
            false /* deref link */);

        NamingEnumeration results;
        try {
            results = searchAux(name, "objectclass=*", constraints, relative,
                true, new Continuation());

        } catch (NamingException ne) {
            if (!clnt.isLdapv3 && currentDN.length() == 0 && name.isEmpty()) {
                // we got an error looking for a root entry on an ldapv2
                // server. The server must not support schema.
                throw new OperationNotSupportedException(
                    "Cannot get schema information from server");
            } else {
                throw ne;
            }
        }

        if (!results.hasMoreElements()) {
            throw new ConfigurationException(
                "Requesting schema of nonexistent entry: " + name);
        }

        SearchResult result = (SearchResult) results.next();
        results.close();

        Attribute schemaEntryAttr =
            result.getAttributes().get("subschemasubentry");
        //System.err.println("schema entry attrs: " + schemaEntryAttr);

        if (schemaEntryAttr == null || schemaEntryAttr.size() < 0) {
            if (currentDN.length() == 0 && name.isEmpty()) {
                // the server doesn't have a subschemasubentry in its root DSE.
                // therefore, it doesn't support schema.
                throw new OperationNotSupportedException(
                    "Cannot read subschemasubentry of root DSE");
            } else {
                return getSchemaEntry(new CompositeName(), false);
            }
        }

        return (String)(schemaEntryAttr.get()); // return schema entry name
    }

    // package-private; used by search enum.
    // Set attributes to point to this context in case some one
    // asked for their schema
    void setParents(Attributes attrs, Name name) throws NamingException {
        NamingEnumeration ae = attrs.getAll();
        while(ae.hasMore()) {
            ((LdapAttribute) ae.next()).setParent(this, name);
        }
    }

    /*
     * Returns the URL associated with this context; used by LdapAttribute
     * after deserialization to get pointer to this context.
     */
    String getURL() {
        if (url == null) {
            url = LdapURL.toUrlString(hostname, port_number, currentDN,
                hasLdapsScheme);
        }

        return url;
    }

   // --------------------- Searches -----------------------------
    protected NamingEnumeration c_search(Name name,
                                         Attributes matchingAttributes,
                                         Continuation cont)
            throws NamingException {
        return c_search(name, matchingAttributes, null, cont);
    }

    protected NamingEnumeration c_search(Name name,
                                         Attributes matchingAttributes,
                                         String[] attributesToReturn,
                                         Continuation cont)
            throws NamingException {
        SearchControls cons = new SearchControls();
        cons.setReturningAttributes(attributesToReturn);
        String filter;
        try {
            filter = SearchFilter.format(matchingAttributes);
        } catch (NamingException e) {
            cont.setError(this, name);
            throw cont.fillInException(e);
        }
        return c_search(name, filter, cons, cont);
    }

    protected NamingEnumeration c_search(Name name,
                                         String filter,
                                         SearchControls cons,
                                         Continuation cont)
            throws NamingException {
        return searchAux(name, filter, cloneSearchControls(cons), true, true,
                         cont);
    }

    protected NamingEnumeration c_search(Name name,
                                         String filterExpr,
                                         Object[] filterArgs,
                                         SearchControls cons,
                                         Continuation cont)
            throws NamingException {
        String strfilter;
        try {
            strfilter = SearchFilter.format(filterExpr, filterArgs);
        } catch (NamingException e) {
            cont.setError(this, name);
            throw cont.fillInException(e);
        }
        return c_search(name, strfilter, cons, cont);
    }

        // Used by NamingNotifier
    NamingEnumeration searchAux(Name name,
        String filter,
        SearchControls cons,
        boolean relative,
        boolean waitForReply, Continuation cont) throws NamingException {

        LdapResult answer = null;
        String[] tokens = new String[2];    // stores ldap compare op. values
        String[] reqAttrs;                  // remember what was asked

        if (cons == null) {
            cons = new SearchControls();
        }
        reqAttrs = cons.getReturningAttributes();

        // if objects are requested then request the Java attributes too
        // so that the objects can be constructed
        if (cons.getReturningObjFlag()) {
            if (reqAttrs != null) {

                // check for presence of "*" (user attributes wildcard)
                boolean hasWildcard = false;
                for (int i = reqAttrs.length - 1; i >= 0; i--) {
                    if (reqAttrs[i].equals("*")) {
                        hasWildcard = true;
                        break;
                    }
                }
                if (! hasWildcard) {
                    String[] totalAttrs =
                        new String[reqAttrs.length +Obj.JAVA_ATTRIBUTES.length];
                    System.arraycopy(reqAttrs, 0, totalAttrs, 0,
                        reqAttrs.length);
                    System.arraycopy(Obj.JAVA_ATTRIBUTES, 0, totalAttrs,
                        reqAttrs.length, Obj.JAVA_ATTRIBUTES.length);

                    cons.setReturningAttributes(totalAttrs);
                }
            }
        }

        LdapCtx.SearchArgs args =
            new LdapCtx.SearchArgs(name, filter, cons, reqAttrs);

        cont.setError(this, name);
        try {
            // see if this can be done as a compare, otherwise do a search
            if (searchToCompare(filter, cons, tokens)){
                //System.err.println("compare triggered");
                answer = compare(name, tokens[0], tokens[1]);
                if (! (answer.compareToSearchResult(fullyQualifiedName(name)))){
                    processReturnCode(answer, name);
                }
            } else {
                answer = doSearch(name, filter, cons, relative, waitForReply);
                // search result may contain referrals
                processReturnCode(answer, name);
            }
            return new LdapSearchEnumeration(this, answer,
                fullyQualifiedName(name), args, cont);

        } catch (LdapReferralException e) {
            if (handleReferrals == LdapClient.LDAP_REF_THROW)
                throw cont.fillInException(e);

            // process the referrals sequentially
            while (true) {

                LdapReferralContext refCtx =
                    (LdapReferralContext)e.getReferralContext(envprops, bindCtls);

                // repeat the original operation at the new context
                try {

                    return refCtx.search(name, filter, cons);

                } catch (LdapReferralException re) {
                    e = re;
                    continue;

                } finally {
                    // Make sure we close referral context
                    refCtx.close();
                }
            }

        } catch (LimitExceededException e) {
            LdapSearchEnumeration res =
                new LdapSearchEnumeration(this, answer, fullyQualifiedName(name),
                                          args, cont);
            res.setNamingException(e);
            return res;

        } catch (PartialResultException e) {
            LdapSearchEnumeration res =
                new LdapSearchEnumeration(this, answer, fullyQualifiedName(name),
                                          args, cont);

            res.setNamingException(e);
            return res;

        } catch (IOException e) {
            NamingException e2 = new CommunicationException(e.getMessage());
            e2.setRootCause(e);
            throw cont.fillInException(e2);

        } catch (NamingException e) {
            throw cont.fillInException(e);
        }
    }


    LdapResult getSearchReply(LdapClient eClnt, LdapResult res)
            throws NamingException {
        // ensureOpen() won't work here because
        // session was associated with previous connection

        // %%% RL: we can actually allow the enumeration to continue
        // using the old handle but other weird things might happen
        // when we hit a referral
        if (clnt != eClnt) {
            throw new CommunicationException(
                "Context's connection changed; unable to continue enumeration");
        }

        try {
            return eClnt.getSearchReply(batchSize, res, binaryAttrs);
        } catch (IOException e) {
            NamingException e2 = new CommunicationException(e.getMessage());
            e2.setRootCause(e);
            throw e2;
        }
    }

    // Perform a search. Expect 1 SearchResultEntry and the SearchResultDone.
    private LdapResult doSearchOnce(Name name, String filter,
        SearchControls cons, boolean relative) throws NamingException {

        int savedBatchSize = batchSize;
        batchSize = 2; // 2 protocol elements

        LdapResult answer = doSearch(name, filter, cons, relative, true);

        batchSize = savedBatchSize;
        return answer;
    }

    private LdapResult doSearch(Name name, String filter, SearchControls cons,
        boolean relative, boolean waitFirstReply) throws NamingException {
            ensureOpen();
            try {
                int scope;

                switch (cons.getSearchScope()) {
                case SearchControls.OBJECT_SCOPE:
                    scope = LdapClient.SCOPE_BASE_OBJECT;
                    break;
                default:
                case SearchControls.ONELEVEL_SCOPE:
                    scope = LdapClient.SCOPE_ONE_LEVEL;
                    break;
                case SearchControls.SUBTREE_SCOPE:
                    scope = LdapClient.SCOPE_SUBTREE;
                    break;
                }

                // If cons.getReturningObjFlag() then caller should already
                // have make sure to request the appropriate attrs

                String[] retattrs = cons.getReturningAttributes();
                if (retattrs != null && retattrs.length == 0) {
                    // Ldap treats null and empty array the same
                    // need to replace with single element array
                    retattrs = new String[1];
                    retattrs[0] = "1.1";
                }

                String nm = (relative
                             ? fullyQualifiedName(name)
                             : (name.isEmpty()
                                ? ""
                                : name.get(0)));

                // JNDI unit is milliseconds, LDAP unit is seconds.
                // Zero means no limit.
                int msecLimit = cons.getTimeLimit();
                int secLimit = 0;

                if (msecLimit > 0) {
                    secLimit = (msecLimit / 1000) + 1;
                }

                LdapResult answer =
                    clnt.search(nm,
                        scope,
                        derefAliases,
                        (int)cons.getCountLimit(),
                        secLimit,
                        cons.getReturningObjFlag() ? false : typesOnly,
                        retattrs,
                        filter,
                        batchSize,
                        reqCtls,
                        binaryAttrs,
                        waitFirstReply);
                respCtls = answer.resControls; // retrieve response controls
                return answer;

            } catch (IOException e) {
                NamingException e2 = new CommunicationException(e.getMessage());
                e2.setRootCause(e);
                throw e2;
            }
    }


    /*
     * Certain simple JNDI searches are automatically converted to
     * LDAP compare operations by the LDAP service provider. A search
     * is converted to a compare iff:
     *
     *    - the scope is set to OBJECT_SCOPE
     *    - the filter string contains a simple assertion: "<type>=<value>"
     *    - the returning attributes list is present but empty
     */

    // returns true if a search can be caried out as a compare, and sets
    // tokens[0] and tokens[1] to the type and value respectively.
    // e.g. filter "cn=Jon Ruiz" becomes, type "cn" and value "Jon Ruiz"
    // This function uses the documents JNDI Compare example as a model
    // for when to turn a search into a compare.

    private static boolean searchToCompare(
                                    String filter,
                                    SearchControls cons,
                                    String tokens[]) {

        // if scope is not object-scope, it's really a search
        if (cons.getSearchScope() != SearchControls.OBJECT_SCOPE) {
            return false;
        }

        // if attributes are to be returned, it's really a search
        String[] attrs = cons.getReturningAttributes();
        if (attrs == null || attrs.length != 0) {
            return false;
        }

        // if the filter not a simple assertion, it's really a search
        if (! filterToAssertion(filter, tokens)) {
            return false;
        }

        // it can be converted to a compare
        return true;
    }

    // If the supplied filter is a simple assertion i.e. "<type>=<value>"
    // (enclosing parentheses are permitted) then
    // filterToAssertion will return true and pass the type and value as
    // the first and second elements of tokens respectively.
    // precondition: tokens[] must be initialized and be at least of size 2.

    private static boolean filterToAssertion(String filter, String tokens[]) {

        // find the left and right half of the assertion
        StringTokenizer assertionTokenizer = new StringTokenizer(filter, "=");

        if (assertionTokenizer.countTokens() != 2) {
            return false;
        }

        tokens[0] = assertionTokenizer.nextToken();
        tokens[1] = assertionTokenizer.nextToken();

        // make sure the value does not contain a wildcard
        if (tokens[1].indexOf('*') != -1) {
            return false;
        }

        // test for enclosing parenthesis
        boolean hasParens = false;
        int len = tokens[1].length();

        if ((tokens[0].charAt(0) == '(') &&
            (tokens[1].charAt(len - 1) == ')')) {
            hasParens = true;

        } else if ((tokens[0].charAt(0) == '(') ||
            (tokens[1].charAt(len - 1) == ')')) {
            return false; // unbalanced
        }

        // make sure the left and right half are not expresions themselves
        StringTokenizer illegalCharsTokenizer =
            new StringTokenizer(tokens[0], "()&|!=~><*", true);

        if (illegalCharsTokenizer.countTokens() != (hasParens ? 2 : 1)) {
            return false;
        }

        illegalCharsTokenizer =
            new StringTokenizer(tokens[1], "()&|!=~><*", true);

        if (illegalCharsTokenizer.countTokens() != (hasParens ? 2 : 1)) {
            return false;
        }

        // strip off enclosing parenthesis, if present
        if (hasParens) {
            tokens[0] = tokens[0].substring(1);
            tokens[1] = tokens[1].substring(0, len - 1);
        }

        return true;
    }

    private LdapResult compare(Name name, String type, String value)
        throws IOException, NamingException {

        ensureOpen();
        String nm = fullyQualifiedName(name);

        LdapResult answer = clnt.compare(nm, type, value, reqCtls);
        respCtls = answer.resControls; // retrieve response controls

        return answer;
    }

    private static SearchControls cloneSearchControls(SearchControls cons) {
        if (cons == null) {
            return null;
        }
        String[] retAttrs = cons.getReturningAttributes();
        if (retAttrs != null) {
            String[] attrs = new String[retAttrs.length];
            System.arraycopy(retAttrs, 0, attrs, 0, retAttrs.length);
            retAttrs = attrs;
        }
        return new SearchControls(cons.getSearchScope(),
                                  cons.getCountLimit(),
                                  cons.getTimeLimit(),
                                  retAttrs,
                                  cons.getReturningObjFlag(),
                                  cons.getDerefLinkFlag());
    }

   // -------------- Environment Properties ------------------

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

    public Hashtable getEnvironment() throws NamingException {
        return (envprops == null
                ? new Hashtable(5, 0.75f)
                : (Hashtable)envprops.clone());
    }

    public Object removeFromEnvironment(String propName)
        throws NamingException {

        // not there; just return
        if (envprops == null || envprops.get(propName) == null) {
            return null;
        }

        if (propName.equals(REF_SEPARATOR)) {
            addrEncodingSeparator = DEFAULT_REF_SEPARATOR;
        } else if (propName.equals(TYPES_ONLY)) {
            typesOnly = DEFAULT_TYPES_ONLY;
        } else if (propName.equals(DELETE_RDN)) {
            deleteRDN = DEFAULT_DELETE_RDN;
        } else if (propName.equals(DEREF_ALIASES)) {
            derefAliases = DEFAULT_DEREF_ALIASES;
        } else if (propName.equals(Context.BATCHSIZE)) {
            batchSize = DEFAULT_BATCH_SIZE;
        } else if (propName.equals(REFERRAL_LIMIT)) {
            referralHopLimit = DEFAULT_REFERRAL_LIMIT;
        } else if (propName.equals(Context.REFERRAL)) {
            setReferralMode(null, true);
        } else if (propName.equals(BINARY_ATTRIBUTES)) {
            setBinaryAttributes(null);
        } else if (propName.equals(CONNECT_TIMEOUT)) {
            connectTimeout = -1;
        } else if (propName.equals(READ_TIMEOUT)) {
            readTimeout = -1;

// The following properties affect the connection

        } else if (propName.equals(Context.SECURITY_PROTOCOL)) {
            closeConnection(SOFT_CLOSE);
            // De-activate SSL and reset the context's url and port number
            if (useSsl && !hasLdapsScheme) {
                useSsl = false;
                url = null;
                if (useDefaultPortNumber) {
                    port_number = DEFAULT_PORT;
                }
            }
        } else if (propName.equals(VERSION) ||
            propName.equals(SOCKET_FACTORY)) {
            closeConnection(SOFT_CLOSE);
        } else if(propName.equals(Context.SECURITY_AUTHENTICATION) ||
            propName.equals(Context.SECURITY_PRINCIPAL) ||
            propName.equals(Context.SECURITY_CREDENTIALS)) {
            sharable = false;
        }

        // Update environment; reconnection will use new props
        envprops = (Hashtable)envprops.clone();
        return envprops.remove(propName);
    }

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

            // If adding null, call remove
            if (propVal == null) {
                return removeFromEnvironment(propName);
            }

            if (propName.equals(REF_SEPARATOR)) {
                setRefSeparator((String)propVal);
            } else if (propName.equals(TYPES_ONLY)) {
                setTypesOnly((String)propVal);
            } else if (propName.equals(DELETE_RDN)) {
                setDeleteRDN((String)propVal);
            } else if (propName.equals(DEREF_ALIASES)) {
                setDerefAliases((String)propVal);
            } else if (propName.equals(Context.BATCHSIZE)) {
                setBatchSize((String)propVal);
            } else if (propName.equals(REFERRAL_LIMIT)) {
                setReferralLimit((String)propVal);
            } else if (propName.equals(Context.REFERRAL)) {
                setReferralMode((String)propVal, true);
            } else if (propName.equals(BINARY_ATTRIBUTES)) {
                setBinaryAttributes((String)propVal);
            } else if (propName.equals(CONNECT_TIMEOUT)) {
                setConnectTimeout((String)propVal);
            } else if (propName.equals(READ_TIMEOUT)) {
                setReadTimeout((String)propVal);
// The following properties affect the connection

            } else if (propName.equals(Context.SECURITY_PROTOCOL)) {
                closeConnection(SOFT_CLOSE);
                // Activate SSL and reset the context's url and port number
                if ("ssl".equals(propVal)) {
                    useSsl = true;
                    url = null;
                    if (useDefaultPortNumber) {
                        port_number = DEFAULT_SSL_PORT;
                    }
                }
            } else if (propName.equals(VERSION) ||
                propName.equals(SOCKET_FACTORY)) {
                closeConnection(SOFT_CLOSE);
            } else if (propName.equals(Context.SECURITY_AUTHENTICATION) ||
                propName.equals(Context.SECURITY_PRINCIPAL) ||
                propName.equals(Context.SECURITY_CREDENTIALS)) {
                sharable = false;
            }

            // Update environment; reconnection will use new props
            envprops = (envprops == null
                ? new Hashtable(5, 0.75f)
                : (Hashtable)envprops.clone());
            return envprops.put(propName, propVal);
    }

    /**
     * Sets the URL that created the context in the java.naming.provider.url
     * property.
     */
    void setProviderUrl(String providerUrl) { // called by LdapCtxFactory
        if (envprops != null) {
            envprops.put(Context.PROVIDER_URL, providerUrl);
        }
    }

    /**
     * Sets the domain name for the context in the com.sun.jndi.ldap.domainname
     * property.
     * Used for hostname verification by Start TLS
     */
    void setDomainName(String domainName) { // called by LdapCtxFactory
        if (envprops != null) {
            envprops.put(DOMAIN_NAME, domainName);
        }
    }

    private void initEnv() throws NamingException {
        if (envprops == null) {
            // Make sure that referrals are to their default
            setReferralMode(null, false);
            return;
        }

        // Set batch size
        setBatchSize((String)envprops.get(Context.BATCHSIZE));

        // Set separator used for encoding RefAddr
        setRefSeparator((String)envprops.get(REF_SEPARATOR));

        // Set whether RDN is removed when renaming object
        setDeleteRDN((String)envprops.get(DELETE_RDN));

        // Set whether types are returned only
        setTypesOnly((String)envprops.get(TYPES_ONLY));

        // Set how aliases are dereferenced
        setDerefAliases((String)envprops.get(DEREF_ALIASES));

        // Set the limit on referral chains
        setReferralLimit((String)envprops.get(REFERRAL_LIMIT));

        setBinaryAttributes((String)envprops.get(BINARY_ATTRIBUTES));

        bindCtls = cloneControls((Control[]) envprops.get(BIND_CONTROLS));

        // set referral handling
        setReferralMode((String)envprops.get(Context.REFERRAL), false);

        // Set the connect timeout
        setConnectTimeout((String)envprops.get(CONNECT_TIMEOUT));

        // Set the read timeout
        setReadTimeout((String)envprops.get(READ_TIMEOUT));

        // When connection is created, it will use these and other
        // properties from the environment
    }

    private void setDeleteRDN(String deleteRDNProp) {
        if ((deleteRDNProp != null) &&
            (deleteRDNProp.equalsIgnoreCase("false"))) {
            deleteRDN = false;
        } else {
            deleteRDN = DEFAULT_DELETE_RDN;
        }
    }

    private void setTypesOnly(String typesOnlyProp) {
        if ((typesOnlyProp != null) &&
            (typesOnlyProp.equalsIgnoreCase("true"))) {
            typesOnly = true;
        } else {
            typesOnly = DEFAULT_TYPES_ONLY;
        }
    }

    /**
     * Sets the batch size of this context;
     */
    private void setBatchSize(String batchSizeProp) {
        // set batchsize
        if (batchSizeProp != null) {
            batchSize = Integer.parseInt(batchSizeProp);
        } else {
            batchSize = DEFAULT_BATCH_SIZE;
        }
    }

    /**
     * Sets the referral mode of this context to 'follow', 'throw' or 'ignore'.
     * If referral mode is 'ignore' then activate the manageReferral control.
     */
    private void setReferralMode(String ref, boolean update) {
        // First determine the referral mode
        if (ref != null) {
            if (ref.equals("follow")) {
                handleReferrals = LdapClient.LDAP_REF_FOLLOW;
            } else if (ref.equals("throw")) {
                handleReferrals = LdapClient.LDAP_REF_THROW;
            } else if (ref.equals("ignore")) {
                handleReferrals = LdapClient.LDAP_REF_IGNORE;
            } else {
                throw new IllegalArgumentException(
                    "Illegal value for " + Context.REFERRAL + " property.");
            }
        } else {
            handleReferrals = DEFAULT_REFERRAL_MODE;
        }

        if (handleReferrals == LdapClient.LDAP_REF_IGNORE) {
            // If ignoring referrals, add manageReferralControl
            reqCtls = addControl(reqCtls, manageReferralControl);

        } else if (update) {

            // If we're update an existing context, remove the control
            reqCtls = removeControl(reqCtls, manageReferralControl);

        } // else, leave alone; need not update
    }

    /**
     * Set whether aliases are derefereced during resolution and searches.
     */
    private void setDerefAliases(String deref) {
        if (deref != null) {
            if (deref.equals("never")) {
                derefAliases = 0; // never de-reference aliases
            } else if (deref.equals("searching")) {
                derefAliases = 1; // de-reference aliases during searching
            } else if (deref.equals("finding")) {
                derefAliases = 2; // de-reference during name resolution
            } else if (deref.equals("always")) {
                derefAliases = 3; // always de-reference aliases
            } else {
                throw new IllegalArgumentException("Illegal value for " +
                    DEREF_ALIASES + " property.");
            }
        } else {
            derefAliases = DEFAULT_DEREF_ALIASES;
        }
    }

    private void setRefSeparator(String sepStr) throws NamingException {
        if (sepStr != null && sepStr.length() > 0) {
            addrEncodingSeparator = sepStr.charAt(0);
        } else {
            addrEncodingSeparator = DEFAULT_REF_SEPARATOR;
        }
    }

    /**
     * Sets the limit on referral chains
     */
    private void setReferralLimit(String referralLimitProp) {
        // set referral limit
        if (referralLimitProp != null) {
            referralHopLimit = Integer.parseInt(referralLimitProp);

            // a zero setting indicates no limit
            if (referralHopLimit == 0)
                referralHopLimit = Integer.MAX_VALUE;
        } else {
            referralHopLimit = DEFAULT_REFERRAL_LIMIT;
        }
    }

    // For counting referral hops
    void setHopCount(int hopCount) {
        this.hopCount = hopCount;
    }

    /**
     * Sets the connect timeout value
     */
    private void setConnectTimeout(String connectTimeoutProp) {
        if (connectTimeoutProp != null) {
            connectTimeout = Integer.parseInt(connectTimeoutProp);
        } else {
            connectTimeout = -1;
        }
    }

    /**
     * Sets the read timeout value
     */
    private void setReadTimeout(String readTimeoutProp) {
        if (readTimeoutProp != null) {
           readTimeout = Integer.parseInt(readTimeoutProp);
        } else {
            readTimeout = -1;
        }
    }

    /*
     * Extract URLs from a string. The format of the string is:
     *
     *     <urlstring > ::= "Referral:" <ldapurls>
     *     <ldapurls>   ::= <separator> <ldapurl> | <ldapurls>
     *     <separator>  ::= ASCII linefeed character (0x0a)
     *     <ldapurl>    ::= LDAP URL format (RFC 1959)
     */
    private static Vector extractURLs(String refString) {

        int separator = 0;
        int urlCount = 0;

        // count the number of URLs
        while ((separator = refString.indexOf('\n', separator)) >= 0) {
            separator++;
            urlCount++;
        }

        Vector referrals = new Vector(urlCount);
        int iURL;
        int i = 0;

        separator = refString.indexOf('\n');
        iURL = separator + 1;
        while ((separator = refString.indexOf('\n', iURL)) >= 0) {
            referrals.addElement(refString.substring(iURL, separator));
            iURL = separator + 1;
        }
        referrals.addElement(refString.substring(iURL));

        return referrals;
    }

    /*
     * Argument is a space-separated list of attribute IDs
     * Converts attribute IDs to lowercase before adding to built-in list.
     */
    private void setBinaryAttributes(String attrIds) {
        if (attrIds == null) {
            binaryAttrs = null;
        } else {
            binaryAttrs = new Hashtable(11, 0.75f);
            StringTokenizer tokens =
                new StringTokenizer(attrIds.toLowerCase(), " ");

            while (tokens.hasMoreTokens()) {
                binaryAttrs.put(tokens.nextToken(), Boolean.TRUE);
            }
        }
    }

   // ----------------- Connection  ---------------------

    protected void finalize() {
        try {
            close();
        } catch (NamingException e) {
            // ignore failures
        }
    }

    synchronized public void close() throws NamingException {
        if (debug) {
            System.err.println("LdapCtx: close() called " + this);
            (new Throwable()).printStackTrace();
        }

        // Event (normal and unsolicited)
        if (eventSupport != null) {
            eventSupport.cleanup(); // idempotent
            removeUnsolicited();
        }

        // Enumerations that are keeping the connection alive
        if (enumCount > 0) {
            if (debug)
                System.err.println("LdapCtx: close deferred");
            closeRequested = true;
            return;
        }
        closeConnection(SOFT_CLOSE);

// %%%: RL: There is no need to set these to null, as they're just
// variables whose contents and references will automatically
// be cleaned up when they're no longer referenced.
// Also, setting these to null creates problems for the attribute
// schema-related methods, which need these to work.
/*
        schemaTrees = null;
        envprops = null;
*/
    }

    public void reconnect(Control[] connCtls) throws NamingException {
        // Update environment
        envprops = (envprops == null
                ? new Hashtable(5, 0.75f)
                : (Hashtable)envprops.clone());

        if (connCtls == null) {
            envprops.remove(BIND_CONTROLS);
            bindCtls = null;
        } else {
            envprops.put(BIND_CONTROLS, bindCtls = cloneControls(connCtls));
        }

        sharable = false;  // can't share with existing contexts
        ensureOpen();      // open or reauthenticated
    }

    private void ensureOpen() throws NamingException {
        ensureOpen(false);
    }

    private void ensureOpen(boolean startTLS) throws NamingException {

        try {
            if (clnt == null) {
                if (debug) {
                    System.err.println("LdapCtx: Reconnecting " + this);
                }

                // reset the cache before a new connection is established
                schemaTrees = new Hashtable(11, 0.75f);
                connect(startTLS);

            } else if (!sharable || startTLS) {

                synchronized (clnt) {
                    if (!clnt.isLdapv3
                        || clnt.referenceCount > 1
                        || clnt.usingSaslStreams()) {
                        closeConnection(SOFT_CLOSE);
                    }
                }
                // reset the cache before a new connection is established
                schemaTrees = new Hashtable(11, 0.75f);
                connect(startTLS);
            }

        } finally {
            sharable = true;   // connection is now either new or single-use
                               // OK for others to start sharing again
        }
    }

    private void connect(boolean startTLS) throws NamingException {
        if (debug) { System.err.println("LdapCtx: Connecting " + this); }

        String user = null;             // authenticating user
        Object passwd = null;           // password for authenticating user
        String secProtocol = null;      // security protocol (e.g. "ssl")
        String socketFactory = null;    // socket factory
        String authMechanism = null;    // authentication mechanism
        String ver = null;
        int ldapVersion;                // LDAP protocol version
        boolean usePool = false;        // enable connection pooling

        if (envprops != null) {
            user = (String)envprops.get(Context.SECURITY_PRINCIPAL);
            passwd = envprops.get(Context.SECURITY_CREDENTIALS);
            ver = (String)envprops.get(VERSION);
            secProtocol =
               useSsl ? "ssl" : (String)envprops.get(Context.SECURITY_PROTOCOL);
            socketFactory = (String)envprops.get(SOCKET_FACTORY);
            authMechanism =
                (String)envprops.get(Context.SECURITY_AUTHENTICATION);

            usePool = "true".equalsIgnoreCase((String)envprops.get(ENABLE_POOL));
        }

        if (socketFactory == null) {
            socketFactory =
                "ssl".equals(secProtocol) ? DEFAULT_SSL_FACTORY : null;
        }

        if (authMechanism == null) {
            authMechanism = (user == null) ? "none" : "simple";
        }

        try {
            boolean initial = (clnt == null);

            if (initial) {
                ldapVersion = (ver != null) ? Integer.parseInt(ver) :
                    DEFAULT_LDAP_VERSION;

                clnt = LdapClient.getInstance(
                    usePool, // Whether to use connection pooling

                    // Required for LdapClient constructor
                    hostname,
                    port_number,
                    socketFactory,
                    connectTimeout,
                    readTimeout,
                    trace,

                    // Required for basic client identity
                    ldapVersion,
                    authMechanism,
                    bindCtls,
                    secProtocol,

                    // Required for simple client identity
                    user,
                    passwd,

                    // Required for SASL client identity
                    envprops);


                /**
                 * Pooled connections are preauthenticated;
                 * newly created ones are not.
                 */
                if (clnt.authenticateCalled()) {
                    return;
                }

            } else if (sharable && startTLS) {
                return; // no authentication required

            } else {
                // reauthenticating over existing connection;
                // only v3 supports this
                ldapVersion = LdapClient.LDAP_VERSION3;
            }

            LdapResult answer = clnt.authenticate(initial,
                user, passwd, ldapVersion, authMechanism, bindCtls, envprops);

            respCtls = answer.resControls; // retrieve (bind) response controls

            if (answer.status != LdapClient.LDAP_SUCCESS) {
                if (initial) {
                    closeConnection(HARD_CLOSE);  // hard close
                }
                processReturnCode(answer);
            }

        } catch (LdapReferralException e) {
            if (handleReferrals == LdapClient.LDAP_REF_THROW)
                throw e;

            String referral;
            LdapURL url;
            NamingException saved_ex = null;

            // Process the referrals sequentially (top level) and
            // recursively (per referral)
            while (true) {

                if ((referral = e.getNextReferral()) == null) {
                    // No more referrals to follow

                    if (saved_ex != null) {
                        throw (NamingException)(saved_ex.fillInStackTrace());
                    } else {
                        // No saved exception, something must have gone wrong
                        throw new NamingException(
                        "Internal error processing referral during connection");
                    }
                }

                // Use host/port number from referral
                url = new LdapURL(referral);
                hostname = url.getHost();
                if ((hostname != null) && (hostname.charAt(0) == '[')) {
                    hostname = hostname.substring(1, hostname.length() - 1);
                }
                port_number = url.getPort();

                // Try to connect again using new host/port number
                try {
                    connect(startTLS);
                    break;

                } catch (NamingException ne) {
                    saved_ex = ne;
                    continue; // follow another referral
                }
            }
        }
    }

    private void closeConnection(boolean hardclose) {
        removeUnsolicited();            // idempotent

        if (clnt != null) {
            if (debug) {
                System.err.println("LdapCtx: calling clnt.close() " + this);
            }
            clnt.close(reqCtls, hardclose);
            clnt = null;
        }
    }

    // Used by Enum classes to track whether it still needs context
    private int enumCount = 0;
    private boolean closeRequested = false;

    synchronized void incEnumCount() {
        ++enumCount;
        if (debug) System.err.println("LdapCtx: " + this + " enum inc: " + enumCount);
    }

    synchronized void decEnumCount() {
        --enumCount;
        if (debug) System.err.println("LdapCtx: " + this + " enum dec: " + enumCount);

        if (enumCount == 0 && closeRequested) {
            try {
                close();
            } catch (NamingException e) {
                // ignore failures
            }
        }
    }


   // ------------ Return code and Error messages  -----------------------

    protected void processReturnCode(LdapResult answer) throws NamingException {
        processReturnCode(answer, null, this, null, envprops, null);
    }

    void processReturnCode(LdapResult answer, Name remainName)
    throws NamingException {
        processReturnCode(answer,
                          (new CompositeName()).add(currentDN),
                          this,
                          remainName,
                          envprops,
                          fullyQualifiedName(remainName));
    }

    protected void processReturnCode(LdapResult res, Name resolvedName,
        Object resolvedObj, Name remainName, Hashtable envprops, String fullDN)
    throws NamingException {

        String msg = LdapClient.getErrorMessage(res.status, res.errorMessage);
        NamingException e;
        LdapReferralException r = null;

        switch (res.status) {

        case LdapClient.LDAP_SUCCESS:

            // handle Search continuation references
            if (res.referrals != null) {

                msg = "Unprocessed Continuation Reference(s)";

                if (handleReferrals == LdapClient.LDAP_REF_IGNORE) {
                    e = new PartialResultException(msg);
                    break;
                }

                // handle multiple sets of URLs
                int contRefCount = res.referrals.size();
                LdapReferralException head = null;
                LdapReferralException ptr = null;

                msg = "Continuation Reference";

                // make a chain of LdapReferralExceptions
                for (int i = 0; i < contRefCount; i++) {

                    r = new LdapReferralException(resolvedName, resolvedObj,
                        remainName, msg, envprops, fullDN, handleReferrals,
                        reqCtls);
                    r.setReferralInfo((Vector)res.referrals.elementAt(i), true);

                    if (hopCount > 1) {
                        r.setHopCount(hopCount);
                    }

                    if (head == null) {
                        head = ptr = r;
                    } else {
                        ptr.nextReferralEx = r; // append ex. to end of chain
                        ptr = r;
                    }
                }
                res.referrals = null;  // reset

                if (res.refEx == null) {
                    res.refEx = head;

                } else {
                    ptr = res.refEx;

                    while (ptr.nextReferralEx != null) {
                        ptr = ptr.nextReferralEx;
                    }
                    ptr.nextReferralEx = head;
                }

                // check the hop limit
                if (hopCount > referralHopLimit) {
                    NamingException lee =
                        new LimitExceededException("Referral limit exceeded");
                    lee.setRootCause(r);
                    throw lee;
                }
            }
            return;

        case LdapClient.LDAP_REFERRAL:

            if (handleReferrals == LdapClient.LDAP_REF_IGNORE) {
                e = new PartialResultException(msg);
                break;
            }

            r = new LdapReferralException(resolvedName, resolvedObj, remainName,
                msg, envprops, fullDN, handleReferrals, reqCtls);
            // only one set of URLs is present
            r.setReferralInfo((Vector)res.referrals.elementAt(0), false);

            if (hopCount > 1) {
                r.setHopCount(hopCount);
            }

            // check the hop limit
            if (hopCount > referralHopLimit) {
                NamingException lee =
                    new LimitExceededException("Referral limit exceeded");
                lee.setRootCause(r);
                e = lee;

            } else {
                e = r;
            }
            break;

        /*
         * Handle SLAPD-style referrals.
         *
         * Referrals received during name resolution should be followed
         * until one succeeds - the target entry is located. An exception
         * is thrown now to handle these.
         *
         * Referrals received during a search operation point to unexplored
         * parts of the directory and each should be followed. An exception
         * is thrown later (during results enumeration) to handle these.
         */

        case LdapClient.LDAP_PARTIAL_RESULTS:

            if (handleReferrals == LdapClient.LDAP_REF_IGNORE) {
                e = new PartialResultException(msg);
                break;
            }

            // extract SLAPD-style referrals from errorMessage
            if ((res.errorMessage != null) && (!res.errorMessage.equals(""))) {
                res.referrals = extractURLs(res.errorMessage);
            } else {
                e = new PartialResultException(msg);
                break;
            }

            // build exception
            r = new LdapReferralException(resolvedName,
                resolvedObj,
                remainName,
                msg,
                envprops,
                fullDN,
                handleReferrals,
                reqCtls);

            if (hopCount > 1) {
                r.setHopCount(hopCount);
            }
            /*
             * %%%
             * SLAPD-style referrals received during name resolution
             * cannot be distinguished from those received during a
             * search operation. Since both must be handled differently
             * the following rule is applied:
             *
             *     If 1 referral and 0 entries is received then
             *     assume name resolution has not yet completed.
             */
            if (((res.entries == null) || (res.entries.size() == 0)) &&
                (res.referrals.size() == 1)) {

                r.setReferralInfo((Vector)res.referrals, false);

                // check the hop limit
                if (hopCount > referralHopLimit) {
                    NamingException lee =
                        new LimitExceededException("Referral limit exceeded");
                    lee.setRootCause(r);
                    e = lee;

                } else {
                    e = r;
                }

            } else {
                r.setReferralInfo(res.referrals, true);
                res.refEx = r;
                return;
            }
            break;

        case LdapClient.LDAP_INVALID_DN_SYNTAX:
        case LdapClient.LDAP_NAMING_VIOLATION:

            if (remainName != null) {
                e = new
                    InvalidNameException(remainName.toString() + ": " + msg);
            } else {
                e = new InvalidNameException(msg);
            }
            break;

        default:
            e = mapErrorCode(res.status, res.errorMessage);
            break;
        }
        e.setResolvedName(resolvedName);
        e.setResolvedObj(resolvedObj);
        e.setRemainingName(remainName);
        throw e;
    }

    /**
     * Maps an LDAP error code to an appropriate NamingException.
     * %%% public; used by controls
     *
     * @param errorCode numeric LDAP error code
     * @param errorMessage textual description of the LDAP error. May be null.
     *
     * @return A NamingException or null if the error code indicates success.
     */
    public static NamingException mapErrorCode(int errorCode,
        String errorMessage) {

        if (errorCode == LdapClient.LDAP_SUCCESS)
            return null;

        NamingException e = null;
        String message = LdapClient.getErrorMessage(errorCode, errorMessage);

        switch (errorCode) {

        case LdapClient.LDAP_ALIAS_DEREFERENCING_PROBLEM:
            e = new NamingException(message);
            break;

        case LdapClient.LDAP_ALIAS_PROBLEM:
            e = new NamingException(message);
            break;

        case LdapClient.LDAP_ATTRIBUTE_OR_VALUE_EXISTS:
            e = new AttributeInUseException(message);
            break;

        case LdapClient.LDAP_AUTH_METHOD_NOT_SUPPORTED:
        case LdapClient.LDAP_CONFIDENTIALITY_REQUIRED:
        case LdapClient.LDAP_STRONG_AUTH_REQUIRED:
        case LdapClient.LDAP_INAPPROPRIATE_AUTHENTICATION:
            e = new AuthenticationNotSupportedException(message);
            break;

        case LdapClient.LDAP_ENTRY_ALREADY_EXISTS:
            e = new NameAlreadyBoundException(message);
            break;

        case LdapClient.LDAP_INVALID_CREDENTIALS:
        case LdapClient.LDAP_SASL_BIND_IN_PROGRESS:
            e = new AuthenticationException(message);
            break;

        case LdapClient.LDAP_INAPPROPRIATE_MATCHING:
            e = new InvalidSearchFilterException(message);
            break;

        case LdapClient.LDAP_INSUFFICIENT_ACCESS_RIGHTS:
            e = new NoPermissionException(message);
            break;

        case LdapClient.LDAP_INVALID_ATTRIBUTE_SYNTAX:
        case LdapClient.LDAP_CONSTRAINT_VIOLATION:
            e =  new InvalidAttributeValueException(message);
            break;

        case LdapClient.LDAP_LOOP_DETECT:
            e = new NamingException(message);
            break;

        case LdapClient.LDAP_NO_SUCH_ATTRIBUTE:
            e = new NoSuchAttributeException(message);
            break;

        case LdapClient.LDAP_NO_SUCH_OBJECT:
            e = new NameNotFoundException(message);
            break;

        case LdapClient.LDAP_OBJECT_CLASS_MODS_PROHIBITED:
        case LdapClient.LDAP_OBJECT_CLASS_VIOLATION:
        case LdapClient.LDAP_NOT_ALLOWED_ON_RDN:
            e = new SchemaViolationException(message);
            break;

        case LdapClient.LDAP_NOT_ALLOWED_ON_NON_LEAF:
            e = new ContextNotEmptyException(message);
            break;

        case LdapClient.LDAP_OPERATIONS_ERROR:
            // %%% need new exception ?
            e = new NamingException(message);
            break;

        case LdapClient.LDAP_OTHER:
            e = new NamingException(message);
            break;

        case LdapClient.LDAP_PROTOCOL_ERROR:
            e = new CommunicationException(message);
            break;

        case LdapClient.LDAP_SIZE_LIMIT_EXCEEDED:
            e = new SizeLimitExceededException(message);
            break;

        case LdapClient.LDAP_TIME_LIMIT_EXCEEDED:
            e = new TimeLimitExceededException(message);
            break;

        case LdapClient.LDAP_UNAVAILABLE_CRITICAL_EXTENSION:
            e = new OperationNotSupportedException(message);
            break;

        case LdapClient.LDAP_UNAVAILABLE:
        case LdapClient.LDAP_BUSY:
            e = new ServiceUnavailableException(message);
            break;

        case LdapClient.LDAP_UNDEFINED_ATTRIBUTE_TYPE:
            e = new InvalidAttributeIdentifierException(message);
            break;

        case LdapClient.LDAP_UNWILLING_TO_PERFORM:
            e = new OperationNotSupportedException(message);
            break;

        case LdapClient.LDAP_COMPARE_FALSE:
        case LdapClient.LDAP_COMPARE_TRUE:
        case LdapClient.LDAP_IS_LEAF:
            // these are really not exceptions and this code probably
            // never gets executed
            e = new NamingException(message);
            break;

        case LdapClient.LDAP_ADMIN_LIMIT_EXCEEDED:
            e = new LimitExceededException(message);
            break;

        case LdapClient.LDAP_REFERRAL:
            e = new NamingException(message);
            break;

        case LdapClient.LDAP_PARTIAL_RESULTS:
            e = new NamingException(message);
            break;

        case LdapClient.LDAP_INVALID_DN_SYNTAX:
        case LdapClient.LDAP_NAMING_VIOLATION:
            e = new InvalidNameException(message);
            break;

        default:
            e = new NamingException(message);
            break;
        }

        return e;
    }

    // ----------------- Extensions and Controls -------------------

    public ExtendedResponse extendedOperation(ExtendedRequest request)
        throws NamingException {

        boolean startTLS = (request.getID().equals(STARTTLS_REQ_OID));
        ensureOpen(startTLS);

        try {

            LdapResult answer =
                clnt.extendedOp(request.getID(), request.getEncodedValue(),
                                reqCtls, startTLS);
            respCtls = answer.resControls; // retrieve response controls

            if (answer.status != LdapClient.LDAP_SUCCESS) {
                processReturnCode(answer, new CompositeName());
            }
            // %%% verify request.getID() == answer.extensionId

            int len = (answer.extensionValue == null) ?
                        0 :
                        answer.extensionValue.length;

            ExtendedResponse er =
                request.createExtendedResponse(answer.extensionId,
                    answer.extensionValue, 0, len);

            if (er instanceof StartTlsResponseImpl) {
                // Pass the connection handle to StartTlsResponseImpl
                String domainName = (String)
                    (envprops != null ? envprops.get(DOMAIN_NAME) : null);
                ((StartTlsResponseImpl)er).setConnection(clnt.conn, domainName);
            }
            return er;

        } catch (LdapReferralException e) {

            if (handleReferrals == LdapClient.LDAP_REF_THROW)
                throw e;

            // process the referrals sequentially
            while (true) {

                LdapReferralContext refCtx =
                    (LdapReferralContext)e.getReferralContext(envprops, bindCtls);

                // repeat the original operation at the new context
                try {

                    return refCtx.extendedOperation(request);

                } catch (LdapReferralException re) {
                    e = re;
                    continue;

                } finally {
                    // Make sure we close referral context
                    refCtx.close();
                }
            }

        } catch (IOException e) {
            NamingException e2 = new CommunicationException(e.getMessage());
            e2.setRootCause(e);
            throw e2;
        }
    }

    public void setRequestControls(Control[] reqCtls) throws NamingException {
        if (handleReferrals == LdapClient.LDAP_REF_IGNORE) {
            this.reqCtls = addControl(reqCtls, manageReferralControl);
        } else {
            this.reqCtls = cloneControls(reqCtls);
        }
    }

    public Control[] getRequestControls() throws NamingException {
        return cloneControls(reqCtls);
    }

    public Control[] getConnectControls() throws NamingException {
        return cloneControls(bindCtls);
    }

    public Control[] getResponseControls() throws NamingException {
        return (respCtls != null)? convertControls(respCtls) : null;
    }

    /**
     * Narrow controls using own default factory and ControlFactory.
     * @param ctls A non-null Vector
     */
    Control[] convertControls(Vector ctls) throws NamingException {
        int count = ctls.size();

        if (count == 0) {
            return null;
        }

        Control[] controls = new Control[count];

        for (int i = 0; i < count; i++) {
            // Try own factory first
            controls[i] = myResponseControlFactory.getControlInstance(
                (Control)ctls.elementAt(i));

            // Try assigned factories if own produced null
            if (controls[i] == null) {
                controls[i] = ControlFactory.getControlInstance(
                (Control)ctls.elementAt(i), this, envprops);
            }
        }
        return controls;
    }

    private static Control[] addControl(Control[] prevCtls, Control addition) {
        if (prevCtls == null) {
            return new Control[]{addition};
        }

        // Find it
        int found = findControl(prevCtls, addition);
        if (found != -1) {
            return prevCtls;  // no need to do it again
        }

        Control[] newCtls = new Control[prevCtls.length+1];
        System.arraycopy(prevCtls, 0, newCtls, 0, prevCtls.length);
        newCtls[prevCtls.length] = addition;
        return newCtls;
    }

    private static int findControl(Control[] ctls, Control target) {
        for (int i = 0; i < ctls.length; i++) {
            if (ctls[i] == target) {
                return i;
            }
        }
        return -1;
    }

    private static Control[] removeControl(Control[] prevCtls, Control target) {
        if (prevCtls == null) {
            return null;
        }

        // Find it
        int found = findControl(prevCtls, target);
        if (found == -1) {
            return prevCtls;  // not there
        }

        // Remove it
        Control[] newCtls = new Control[prevCtls.length-1];
        System.arraycopy(prevCtls, 0, newCtls, 0, found);
        System.arraycopy(prevCtls, found+1, newCtls, found,
            prevCtls.length-found-1);
        return newCtls;
    }

    private static Control[] cloneControls(Control[] ctls) {
        if (ctls == null) {
            return null;
        }
        Control[] copiedCtls = new Control[ctls.length];
        System.arraycopy(ctls, 0, copiedCtls, 0, ctls.length);
        return copiedCtls;
    }

    // -------------------- Events ------------------------
    /*
     * Access to eventSupport need not be synchronized even though the
     * Connection thread can access it asynchronously. It is
     * impossible for a race condition to occur because
     * eventSupport.addNamingListener() must have been called before
     * the Connection thread can call back to this ctx.
     */
    public void addNamingListener(Name nm, int scope, NamingListener l)
        throws NamingException {
            addNamingListener(getTargetName(nm), scope, l);
    }

    public void addNamingListener(String nm, int scope, NamingListener l)
        throws NamingException {
            if (eventSupport == null)
                eventSupport = new EventSupport(this);
            eventSupport.addNamingListener(getTargetName(new CompositeName(nm)),
                scope, l);

            // If first time asking for unsol
            if (l instanceof UnsolicitedNotificationListener && !unsolicited) {
                addUnsolicited();
            }
    }

    public void removeNamingListener(NamingListener l) throws NamingException {
        if (eventSupport == null)
            return; // no activity before, so just return

        eventSupport.removeNamingListener(l);

        // If removing an Unsol listener and it is the last one, let clnt know
        if (l instanceof UnsolicitedNotificationListener &&
            !eventSupport.hasUnsolicited()) {
            removeUnsolicited();
        }
    }

    public void addNamingListener(String nm, String filter, SearchControls ctls,
        NamingListener l) throws NamingException {
            if (eventSupport == null)
                eventSupport = new EventSupport(this);
            eventSupport.addNamingListener(getTargetName(new CompositeName(nm)),
                filter, cloneSearchControls(ctls), l);

            // If first time asking for unsol
            if (l instanceof UnsolicitedNotificationListener && !unsolicited) {
                addUnsolicited();
            }
    }

    public void addNamingListener(Name nm, String filter, SearchControls ctls,
        NamingListener l) throws NamingException {
            addNamingListener(getTargetName(nm), filter, ctls, l);
    }

    public void addNamingListener(Name nm, String filter, Object[] filterArgs,
        SearchControls ctls, NamingListener l) throws NamingException {
            addNamingListener(getTargetName(nm), filter, filterArgs, ctls, l);
    }

    public void addNamingListener(String nm, String filterExpr, Object[] filterArgs,
        SearchControls ctls, NamingListener l) throws NamingException {
        String strfilter = SearchFilter.format(filterExpr, filterArgs);
        addNamingListener(getTargetName(new CompositeName(nm)), strfilter, ctls, l);
    }

    public boolean targetMustExist() {
        return true;
    }

    /**
     * Retrieves the target name for which the listener is registering.
     * If nm is a CompositeName, use its first and only component. It
     * cannot have more than one components because a target be outside of
     * this namespace. If nm is not a CompositeName, then treat it as a
     * compound name.
     * @param nm The non-null target name.
     */
    private static String getTargetName(Name nm) throws NamingException {
        if (nm instanceof CompositeName) {
            if (nm.size() > 1) {
                throw new InvalidNameException(
                    "Target cannot span multiple namespaces: " + nm);
            } else if (nm.size() == 0) {
                return "";
            } else {
                return nm.get(0);
            }
        } else {
            // treat as compound name
            return nm.toString();
        }
    }

    // ------------------ Unsolicited Notification ---------------
    // package private methods for handling unsolicited notification

    /**
     * Registers this context with the underlying LdapClient.
     * When the underlying LdapClient receives an unsolicited notification,
     * it will invoke LdapCtx.fireUnsolicited() so that this context
     * can (using EventSupport) notified any registered listeners.
     * This method is called by EventSupport when an unsolicited listener
     * first registers with this context (should be called just once).
     * @see #removeUnsolicited
     * @see #fireUnsolicited
     */
    private void addUnsolicited() throws NamingException {
        if (debug) {
            System.out.println("LdapCtx.addUnsolicited: " + this);
        }

        // addNamingListener must have created EventSupport already
        ensureOpen();
        synchronized (eventSupport) {
            clnt.addUnsolicited(this);
            unsolicited = true;
        }
    }

    /**
     * Removes this context from registering interest in unsolicited
     * notifications from the underlying LdapClient. This method is called
     * under any one of the following conditions:
     * <ul>
     * <li>All unsolicited listeners have been removed. (see removingNamingListener)
     * <li>This context is closed.
     * <li>This context's underlying LdapClient changes.
     *</ul>
     * After this method has been called, this context will not pass
     * on any events related to unsolicited notifications to EventSupport and
     * and its listeners.
     */

    private void removeUnsolicited() {
        if (debug) {
            System.out.println("LdapCtx.removeUnsolicited: " + unsolicited);
        }
        if (eventSupport == null) {
            return;
        }

        // addNamingListener must have created EventSupport already
        synchronized(eventSupport) {
            if (unsolicited && clnt != null) {
                clnt.removeUnsolicited(this);
            }
            unsolicited = false;
        }
    }

    /**
     * Uses EventSupport to fire an event related to an unsolicited notification.
     * Called by LdapClient when LdapClient receives an unsolicited notification.
     */
    void fireUnsolicited(Object obj) {
        if (debug) {
            System.out.println("LdapCtx.fireUnsolicited: " + obj);
        }
        // addNamingListener must have created EventSupport already
        synchronized(eventSupport) {
            if (unsolicited) {
                eventSupport.fireUnsolicited(obj);

                if (obj instanceof NamingException) {
                    unsolicited = false;
                    // No need to notify clnt because clnt is the
                    // only one that can fire a NamingException to
                    // unsol listeners and it will handle its own cleanup
                }
            }
        }
    }
}
