/*
 * Copyright (c) 1999, 2014, 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.Locale;
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 compatibility

    // 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";

    // Block until the first search reply is received
    private static final String WAIT_FOR_REPLY =
        "com.sun.jndi.ldap.search.waitForReply";

    // Size of the queue of unprocessed search replies
    private static final String REPLY_QUEUE_SIZE =
        "com.sun.jndi.ldap.search.replyQueueSize";

    // ----------------- 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
    private boolean reconnect = false;  // indicates that re-connect requested
    Hashtable<String, java.lang.Object> 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<Control> 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<String, DirContext> 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<String, Boolean> binaryAttrs = null; // attr values returned as byte[]
    private int connectTimeout = -1;         // no timeout value
    private int readTimeout = -1;            // no timeout value
    private boolean waitForReply = true;     // wait for search response
    private int replyQueueSize  = -1;        // unlimited queue size
    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  -----------------------------------

    @SuppressWarnings("unchecked")
    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<String, java.lang.Object>) 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 | 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
     * @return 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)).getRdns();

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

            // Add attributes of RDN to attrs if not already there
            NamingEnumeration<? extends Attribute> enum_ = nameAttrs.getAll();
            Attribute nameAttr;
            while (enum_.hasMore()) {
                nameAttr = 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<String> enumStr,
                                String str) throws NamingException {
        String strEntry;

        while (enumStr.hasMore()) {
             strEntry = 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 second Vector onto the first Vector
     * (v2 must be non-null)
     */
    private static <T> Vector<T> appendVector(Vector<T> v1, Vector<T> 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 = answer.entries.elementAt(0);
                attrs = entry.attributes;

                Vector<Control> 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<NameClassPair> 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<Binding> 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) {
                @SuppressWarnings("unchecked")
                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(cont.fillInException(e));
            return res;

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

            res.setNamingException(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 = answer.entries.elementAt(0);

            Vector<Control> 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<? extends Attribute> ae = attrs.getAll();
            for(int i = 0; i < jmods.length && ae.hasMore(); i++) {
                jmods[i] = jmod_op;
                jattrs[i] = 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 = 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<SearchResult> results =
            searchAux(sse, "(objectClass=subschema)", constraints,
            false, true, new Continuation());

        if(!results.hasMore()) {
            throw new OperationNotSupportedException(
                "Cannot get read subschemasubentry: " + subschemasubentry);
        }
        SearchResult result = 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 tries a search 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<SearchResult> 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 = 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<? extends Attribute> 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<SearchResult> c_search(Name name,
                                         Attributes matchingAttributes,
                                         Continuation cont)
            throws NamingException {
        return c_search(name, matchingAttributes, null, cont);
    }

    protected NamingEnumeration<SearchResult> 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<SearchResult> c_search(Name name,
                                         String filter,
                                         SearchControls cons,
                                         Continuation cont)
            throws NamingException {
        return searchAux(name, filter, cloneSearchControls(cons), true,
                 waitForReply, cont);
    }

    protected NamingEnumeration<SearchResult> 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<SearchResult> 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) {

                @SuppressWarnings("unchecked")
                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 waitForReply) 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,
                        waitForReply,
                        replyQueueSize);
                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 carried 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 expressions 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<String, Object> p_getEnvironment() {
        return envprops;
    }

    @SuppressWarnings("unchecked") // clone()
    public Hashtable<String, Object> getEnvironment() throws NamingException {
        return (envprops == null
                ? new Hashtable<String, Object>(5, 0.75f)
                : (Hashtable<String, Object>)envprops.clone());
    }

    @SuppressWarnings("unchecked") // clone()
    public Object removeFromEnvironment(String propName)
        throws NamingException {

        // not there; just return
        if (envprops == null || envprops.get(propName) == null) {
            return null;
        }
        switch (propName) {
            case REF_SEPARATOR:
                addrEncodingSeparator = DEFAULT_REF_SEPARATOR;
                break;
            case TYPES_ONLY:
                typesOnly = DEFAULT_TYPES_ONLY;
                break;
            case DELETE_RDN:
                deleteRDN = DEFAULT_DELETE_RDN;
                break;
            case DEREF_ALIASES:
                derefAliases = DEFAULT_DEREF_ALIASES;
                break;
            case Context.BATCHSIZE:
                batchSize = DEFAULT_BATCH_SIZE;
                break;
            case REFERRAL_LIMIT:
                referralHopLimit = DEFAULT_REFERRAL_LIMIT;
                break;
            case Context.REFERRAL:
                setReferralMode(null, true);
                break;
            case BINARY_ATTRIBUTES:
                setBinaryAttributes(null);
                break;
            case CONNECT_TIMEOUT:
                connectTimeout = -1;
                break;
            case READ_TIMEOUT:
                readTimeout = -1;
                break;
            case WAIT_FOR_REPLY:
                waitForReply = true;
                break;
            case REPLY_QUEUE_SIZE:
                replyQueueSize = -1;
                break;

            // The following properties affect the connection

            case 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;
                    }
                }
                break;
            case VERSION:
            case SOCKET_FACTORY:
                closeConnection(SOFT_CLOSE);
                break;
            case Context.SECURITY_AUTHENTICATION:
            case Context.SECURITY_PRINCIPAL:
            case Context.SECURITY_CREDENTIALS:
                sharable = false;
                break;
        }

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

    @SuppressWarnings("unchecked") // clone()
    public Object addToEnvironment(String propName, Object propVal)
        throws NamingException {

            // If adding null, call remove
            if (propVal == null) {
                return removeFromEnvironment(propName);
            }
            switch (propName) {
                case REF_SEPARATOR:
                    setRefSeparator((String)propVal);
                    break;
                case TYPES_ONLY:
                    setTypesOnly((String)propVal);
                    break;
                case DELETE_RDN:
                    setDeleteRDN((String)propVal);
                    break;
                case DEREF_ALIASES:
                    setDerefAliases((String)propVal);
                    break;
                case Context.BATCHSIZE:
                    setBatchSize((String)propVal);
                    break;
                case REFERRAL_LIMIT:
                    setReferralLimit((String)propVal);
                    break;
                case Context.REFERRAL:
                    setReferralMode((String)propVal, true);
                    break;
                case BINARY_ATTRIBUTES:
                    setBinaryAttributes((String)propVal);
                    break;
                case CONNECT_TIMEOUT:
                    setConnectTimeout((String)propVal);
                    break;
                case READ_TIMEOUT:
                    setReadTimeout((String)propVal);
                    break;
                case WAIT_FOR_REPLY:
                    setWaitForReply((String)propVal);
                    break;
                case REPLY_QUEUE_SIZE:
                    setReplyQueueSize((String)propVal);
                    break;

            // The following properties affect the connection

                case 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;
                        }
                    }
                    break;
                case VERSION:
                case SOCKET_FACTORY:
                    closeConnection(SOFT_CLOSE);
                    break;
                case Context.SECURITY_AUTHENTICATION:
                case Context.SECURITY_PRINCIPAL:
                case Context.SECURITY_CREDENTIALS:
                    sharable = false;
                    break;
            }

            // Update environment; reconnection will use new props
            envprops = (envprops == null
                ? new Hashtable<String, Object>(5, 0.75f)
                : (Hashtable<String, Object>)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));

        // Set the flag that controls whether to block until the first reply
        // is received
        setWaitForReply((String)envprops.get(WAIT_FOR_REPLY));

        // Set the size of the queue of unprocessed search replies
        setReplyQueueSize((String)envprops.get(REPLY_QUEUE_SIZE));

        // 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) {
            switch (ref) {
                case "follow":
                    handleReferrals = LdapClient.LDAP_REF_FOLLOW;
                    break;
                case "throw":
                    handleReferrals = LdapClient.LDAP_REF_THROW;
                    break;
                case "ignore":
                    handleReferrals = LdapClient.LDAP_REF_IGNORE;
                    break;
                default:
                    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 dereferenced during resolution and searches.
     */
    private void setDerefAliases(String deref) {
        if (deref != null) {
            switch (deref) {
                case "never":
                    derefAliases = 0; // never de-reference aliases
                    break;
                case "searching":
                    derefAliases = 1; // de-reference aliases during searching
                    break;
                case "finding":
                    derefAliases = 2; // de-reference during name resolution
                    break;
                case "always":
                    derefAliases = 3; // always de-reference aliases
                    break;
                default:
                    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 size of the queue of unprocessed search replies
     */
    private void setReplyQueueSize(String replyQueueSizeProp) {
        if (replyQueueSizeProp != null) {
           replyQueueSize = Integer.parseInt(replyQueueSizeProp);
            // disallow an empty queue
            if (replyQueueSize <= 0) {
                replyQueueSize = -1;    // unlimited
            }
        } else {
            replyQueueSize = -1;        // unlimited
        }
    }

    /**
     * Sets the flag that controls whether to block until the first search
     * reply is received
     */
    private void setWaitForReply(String waitForReplyProp) {
        if (waitForReplyProp != null &&
            (waitForReplyProp.equalsIgnoreCase("false"))) {
            waitForReply = false;
        } else {
            waitForReply = true;
        }
    }

    /**
     * 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)
     *
     * Returns a Vector of single-String Vectors.
     */
    private static Vector<Vector<String>> extractURLs(String refString) {

        int separator = 0;
        int urlCount = 0;

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

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

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

        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(Locale.ENGLISH), " ");

            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;
*/
    }

    @SuppressWarnings("unchecked") // clone()
    public void reconnect(Control[] connCtls) throws NamingException {
        // Update environment
        envprops = (envprops == null
                ? new Hashtable<String, Object>(5, 0.75f)
                : (Hashtable<String, Object>)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
        reconnect = true;
        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 || reconnect) {
                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);

                reconnect = false;

                /**
                 * 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(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(res.referrals == null ? null :
                    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.isEmpty())) &&
                ((res.referrals != null) && (res.referrals.size() == 1))) {

                r.setReferralInfo(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>
     */
    Control[] convertControls(Vector<Control> 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(
                ctls.elementAt(i));

            // Try assigned factories if own produced null
            if (controls[i] == null) {
                controls[i] = ControlFactory.getControlInstance(
                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.isEmpty()) {
                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
                }
            }
        }
    }
}
