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

import javax.naming.*;
import javax.naming.spi.NamingManager;
import javax.naming.spi.ResolveResult;

import java.util.Hashtable;
import java.util.Vector;
import java.net.MalformedURLException;
import java.net.URL;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.IOException;

import org.omg.CosNaming.*;
import org.omg.CosNaming.NamingContextPackage.*;
import org.omg.CORBA.*;

import com.sun.jndi.toolkit.corba.CorbaUtils;

// Needed for creating default ORB
import java.applet.Applet;

/**
  * Provides a bridge to the CosNaming server provided by
  * JavaIDL. This class provides the InitialContext from CosNaming.
  *
  * @author Raj Krishnamurthy
  * @author Rosanna Lee
  */

public class CNCtx implements javax.naming.Context {

    private final static boolean debug = false;

    /*
     * Implement one shared ORB among all CNCtx.  However, there is a public constructor
     * accepting an ORB, so we need the option of using a given ORB.
     */
    private static ORB _defaultOrb;
    ORB _orb;                   // used by ExceptionMapper and RMI/IIOP factory
    public NamingContext _nc;   // public for accessing underlying NamingContext

    private synchronized static ORB getDefaultOrb() {
        if (_defaultOrb == null) {
            _defaultOrb = CorbaUtils.getOrb(null, -1,
               new Hashtable<String, java.lang.Object>());
        }
        return _defaultOrb;
    }

    private NameComponent[] _name = null;

    Hashtable _env; // used by ExceptionMapper
    static final CNNameParser parser = new CNNameParser();

    private static final String FED_PROP = "com.sun.jndi.cosnaming.federation";
    boolean federation = false;

    // Reference counter for tracking _orb references
    OrbReuseTracker orbTracker = null;
    int enumCount;
    boolean isCloseCalled = false;

    /**
      * Create a CNCtx object. Gets the initial naming
      * reference for the COS Naming Service from the ORB.
      * The ORB can be passed in via the java.naming.corba.orb property
      * or be created using properties in the environment properties.
      * @param env Environment properties for initializing name service.
      * @exception NamingException Cannot initialize ORB or naming context.
      */
    CNCtx(Hashtable env) throws NamingException {
        if (env != null) {
            env = (Hashtable) env.clone();
        }
        _env = env;
        federation = "true".equals(env != null ? env.get(FED_PROP) : null);
        initOrbAndRootContext(env);
    }

    private CNCtx() {
    }

    /**
     * This method is used by the iiop and iiopname URL Context factories.
     */
    public static ResolveResult createUsingURL(String url, Hashtable env)
    throws NamingException {
        CNCtx ctx = new CNCtx();
        if (env != null) {
            env = (Hashtable) env.clone();
        }
        ctx._env = env;
        String rest = ctx.initUsingUrl(
            env != null ?
                (org.omg.CORBA.ORB) env.get("java.naming.corba.orb")
                : null,
            url, env);

        // rest is the INS name
        // Return the parsed form to prevent subsequent lookup
        // from parsing the string as a composite name
        // The caller should be aware that a toString() of the name,
        // which came from the environment will yield its INS syntax,
        // rather than a composite syntax
        return new ResolveResult(ctx, parser.parse(rest));
    }

    /**
      * Creates a CNCtx object which supports the javax.naming
      * apis given a COS Naming Context object.
      * @param orb The ORB used by this context
      * @param tracker The ORB reuse tracker for tracking references to the
      *  orb object
      * @param nctx The COS NamingContext object associated with this context
      * @param name The name of this context relative to the root
      */

    CNCtx(ORB orb, OrbReuseTracker tracker, NamingContext nctx, Hashtable env,
                        NameComponent[]name)
        throws NamingException {
            if (orb == null || nctx == null)
                throw new ConfigurationException(
                    "Must supply ORB or NamingContext");
            if (orb != null) {
                _orb = orb;
            } else {
                _orb = getDefaultOrb();
            }
            _nc = nctx;
            _env = env;
            _name = name;
            federation = "true".equals(env != null ? env.get(FED_PROP) : null);
    }

    NameComponent[] makeFullName(NameComponent[] child) {
        if (_name == null || _name.length == 0) {
            return child;
        }
        NameComponent[] answer = new NameComponent[_name.length+child.length];

        // parent
        System.arraycopy(_name, 0, answer, 0, _name.length);

        // child
        System.arraycopy(child, 0, answer, _name.length, child.length);
        return answer;
    }


    public String getNameInNamespace() throws NamingException {
        if (_name == null || _name.length == 0) {
            return "";
        }
        return CNNameParser.cosNameToInsString(_name);
    }

    /**
     * These are the URL schemes that need to be processed.
     * IOR and corbaloc URLs can be passed directly to ORB.string_to_object()
     */
    private static boolean isCorbaUrl(String url) {
        return url.startsWith("iiop://")
            || url.startsWith("iiopname://")
            || url.startsWith("corbaname:")
            ;
    }

    /**
      * Initializes the COS Naming Service.
      * This method initializes the three instance fields:
      * _nc : The root naming context.
      * _orb: The ORB to use for connecting RMI/IIOP stubs and for
      *       getting the naming context (_nc) if one was not specified
      *       explicitly via PROVIDER_URL.
      * _name: The name of the root naming context.
      *<p>
      * _orb is obtained from java.naming.corba.orb if it has been set.
      * Otherwise, _orb is created using the host/port from PROVIDER_URL
      * (if it contains an "iiop" or "iiopname" URL), or from initialization
      * properties specified in env.
      *<p>
      * _nc is obtained from the IOR stored in PROVIDER_URL if it has been
      * set and does not contain an "iiop" or "iiopname" URL. It can be
      * a stringified IOR, "corbaloc" URL, "corbaname" URL,
      * or a URL (such as file/http/ftp) to a location
      * containing a stringified IOR. If PROVIDER_URL has not been
      * set in this way, it is obtained from the result of
      *     ORB.resolve_initial_reference("NameService");
      *<p>
      * _name is obtained from the "iiop", "iiopname", or "corbaname" URL.
      * It is the empty name by default.
      *
      * @param env Environment The possibly null environment.
      * @exception NamingException When an error occurs while initializing the
      * ORB or the naming context.
      */
    private void initOrbAndRootContext(Hashtable env) throws NamingException {
        org.omg.CORBA.ORB inOrb = null;
        String ncIor = null;

        if (inOrb == null && env != null) {
            inOrb = (org.omg.CORBA.ORB) env.get("java.naming.corba.orb");
        }

        if (inOrb == null)
            inOrb = getDefaultOrb(); // will create a default ORB if none exists

        // Extract PROVIDER_URL from environment
        String provUrl = null;
        if (env != null) {
            provUrl = (String)env.get(javax.naming.Context.PROVIDER_URL);
        }

        if (provUrl != null && !isCorbaUrl(provUrl)) {
            // Initialize the root naming context by using the IOR supplied
            // in the PROVIDER_URL
            ncIor = getStringifiedIor(provUrl);
            setOrbAndRootContext(inOrb, ncIor);
        } else if (provUrl != null) {
            // Initialize the root naming context by using the URL supplied
            // in the PROVIDER_URL
            String insName = initUsingUrl(inOrb, provUrl, env);

            // If name supplied in URL, resolve it to a NamingContext
            if (insName.length() > 0) {
                _name = parser.nameToCosName(parser.parse(insName));
                try {
                    org.omg.CORBA.Object obj = _nc.resolve(_name);
                    _nc = NamingContextHelper.narrow(obj);
                    if (_nc == null) {
                        throw new ConfigurationException(insName +
                            " does not name a NamingContext");
                    }
                } catch (org.omg.CORBA.BAD_PARAM e) {
                    throw new ConfigurationException(insName +
                        " does not name a NamingContext");
                } catch (Exception e) {
                    throw ExceptionMapper.mapException(e, this, _name);
                }
            }
        } else {
            // No PROVIDER_URL supplied; initialize using defaults
            if (debug) {
                System.err.println("Getting default ORB: " + inOrb + env);
            }
            setOrbAndRootContext(inOrb, (String)null);
        }
    }


    private String initUsingUrl(ORB orb, String url, Hashtable env)
        throws NamingException {
        if (url.startsWith("iiop://") || url.startsWith("iiopname://")) {
            return initUsingIiopUrl(orb, url, env);
        } else {
            return initUsingCorbanameUrl(orb, url, env);
        }
    }

    /**
     * Handles "iiop" and "iiopname" URLs (INS 98-10-11)
     */
    private String initUsingIiopUrl(ORB defOrb, String url, Hashtable env)
        throws NamingException {

        if (defOrb == null)
            defOrb = getDefaultOrb();

        try {
            IiopUrl parsedUrl = new IiopUrl(url);

            Vector addrs = parsedUrl.getAddresses();
            IiopUrl.Address addr;
            NamingException savedException = null;

            for (int i = 0; i < addrs.size(); i++) {
                addr = (IiopUrl.Address)addrs.elementAt(i);

                try {
                    try {
                        String tmpUrl = "corbaloc:iiop:" + addr.host
                            + ":" + addr.port + "/NameService";
                        if (debug) {
                            System.err.println("Using url: " + tmpUrl);
                        }
                        org.omg.CORBA.Object rootCtx =
                            defOrb.string_to_object(tmpUrl);
                        setOrbAndRootContext(defOrb, rootCtx);
                        return parsedUrl.getStringName();
                    } catch (Exception e) {} // keep going

                    // Get ORB
                    if (debug) {
                        System.err.println("Getting ORB for " + addr.host
                            + " and port " + addr.port);
                    }

                    // Assign to fields
                    setOrbAndRootContext(defOrb, (String)null);
                    return parsedUrl.getStringName();

                } catch (NamingException ne) {
                    savedException = ne;
                }
            }
            if (savedException != null) {
                throw savedException;
            } else {
                throw new ConfigurationException("Problem with URL: " + url);
            }
        } catch (MalformedURLException e) {
            throw new ConfigurationException(e.getMessage());
        }
    }

    /**
     * Initializes using "corbaname" URL (INS 99-12-03)
     */
    private String initUsingCorbanameUrl(ORB orb, String url, Hashtable env)
        throws NamingException {

        if (orb == null)
                orb = getDefaultOrb();

        try {
            CorbanameUrl parsedUrl = new CorbanameUrl(url);

            String corbaloc = parsedUrl.getLocation();
            String cosName = parsedUrl.getStringName();

            setOrbAndRootContext(orb, corbaloc);

            return parsedUrl.getStringName();
        } catch (MalformedURLException e) {
            throw new ConfigurationException(e.getMessage());
        }
    }

    private void setOrbAndRootContext(ORB orb, String ncIor)
        throws NamingException {
        _orb = orb;
        try {
            org.omg.CORBA.Object ncRef;
            if (ncIor != null) {
                if (debug) {
                    System.err.println("Passing to string_to_object: " + ncIor);
                }
                ncRef = _orb.string_to_object(ncIor);
            } else {
                ncRef = _orb.resolve_initial_references("NameService");
            }
            if (debug) {
                System.err.println("Naming Context Ref: " + ncRef);
            }
            _nc = NamingContextHelper.narrow(ncRef);
            if (_nc == null) {
                if (ncIor != null) {
                    throw new ConfigurationException(
                        "Cannot convert IOR to a NamingContext: " + ncIor);
                } else {
                    throw new ConfigurationException(
"ORB.resolve_initial_references(\"NameService\") does not return a NamingContext");
                }
            }
        } catch (org.omg.CORBA.ORBPackage.InvalidName in) {
            NamingException ne =
                new ConfigurationException(
"COS Name Service not registered with ORB under the name 'NameService'");
            ne.setRootCause(in);
            throw ne;
        } catch (org.omg.CORBA.COMM_FAILURE e) {
            NamingException ne =
                new CommunicationException("Cannot connect to ORB");
            ne.setRootCause(e);
            throw ne;
        } catch (org.omg.CORBA.BAD_PARAM e) {
            NamingException ne = new ConfigurationException(
                "Invalid URL or IOR: " + ncIor);
            ne.setRootCause(e);
            throw ne;
        } catch (org.omg.CORBA.INV_OBJREF e) {
            NamingException ne = new ConfigurationException(
                "Invalid object reference: " + ncIor);
            ne.setRootCause(e);
            throw ne;
        }
    }

    private void setOrbAndRootContext(ORB orb, org.omg.CORBA.Object ncRef)
        throws NamingException {
        _orb = orb;
        try {
            _nc = NamingContextHelper.narrow(ncRef);
            if (_nc == null) {
                throw new ConfigurationException(
                    "Cannot convert object reference to NamingContext: " + ncRef);
            }
        } catch (org.omg.CORBA.COMM_FAILURE e) {
            NamingException ne =
                new CommunicationException("Cannot connect to ORB");
            ne.setRootCause(e);
            throw ne;
        }
    }

    private String getStringifiedIor(String url) throws NamingException {
        if (url.startsWith("IOR:") || url.startsWith("corbaloc:")) {
            return url;
        } else {
            InputStream in = null;
            try {
                URL u = new URL(url);
                in = u.openStream();
                if (in != null) {
                    BufferedReader bufin =
                        new BufferedReader(new InputStreamReader(in, "8859_1"));
                    String str;
                    while ((str = bufin.readLine()) != null) {
                        if (str.startsWith("IOR:")) {
                            return str;
                        }
                    }
                }
            } catch (IOException e) {
                NamingException ne =
                    new ConfigurationException("Invalid URL: " + url);
                ne.setRootCause(e);
                throw ne;
            } finally {
                try {
                    if (in != null) {
                        in.close();
                    }
                } catch (IOException e) {
                    NamingException ne =
                        new ConfigurationException("Invalid URL: " + url);
                    ne.setRootCause(e);
                    throw ne;
                }
            }
            throw new ConfigurationException(url + " does not contain an IOR");
        }
    }


    /**
      * Does the job of calling the COS Naming API,
      * resolve, and performs the exception mapping. If the resolved
      * object is a COS Naming Context (sub-context), then this function
      * returns a new JNDI naming context object.
      * @param path the NameComponent[] object.
      * @exception NotFound No objects under the name.
      * @exception CannotProceed Unable to obtain a continuation context
      * @exception InvalidName Name not understood.
      * @return Resolved object returned by the COS Name Server.
      */
    java.lang.Object callResolve(NameComponent[] path)
        throws NamingException {
            try {
                org.omg.CORBA.Object obj = _nc.resolve(path);
                try {
                    NamingContext nc =
                        NamingContextHelper.narrow(obj);
                    if (nc != null) {
                        return new CNCtx(_orb, orbTracker, nc, _env,
                                        makeFullName(path));
                    } else {
                        return obj;
                    }
                } catch (org.omg.CORBA.SystemException e) {
                    return obj;
                }
            } catch (Exception e) {
                throw ExceptionMapper.mapException(e, this, path);
            }
    }

    /**
      * Converts the "String" name into a CompositeName
      * returns the object resolved by the COS Naming api,
      * resolve. Returns the current context if the name is empty.
      * Returns either an org.omg.CORBA.Object or javax.naming.Context object.
      * @param name string used to resolve the object.
      * @exception NamingException See callResolve.
      * @return the resolved object
      */
    public java.lang.Object lookup(String name) throws NamingException {
        if (debug) {
            System.out.println("Looking up: " + name);
        }
        return lookup(new CompositeName(name));
    }

    /**
      * Converts the "Name" name into a NameComponent[] object and
      * returns the object resolved by the COS Naming api,
      * resolve. Returns the current context if the name is empty.
      * Returns either an org.omg.CORBA.Object or javax.naming.Context object.
      * @param name JNDI Name used to resolve the object.
      * @exception NamingException See callResolve.
      * @return the resolved object
      */
    public java.lang.Object lookup(Name name)
        throws NamingException {
            if (_nc == null)
                throw new ConfigurationException(
                    "Context does not have a corresponding NamingContext");
            if (name.size() == 0 )
                return this; // %%% should clone() so that env can be changed
            NameComponent[] path = CNNameParser.nameToCosName(name);

            try {
                java.lang.Object answer = callResolve(path);

                try {
                    return NamingManager.getObjectInstance(answer, name, this, _env);
                } catch (NamingException e) {
                    throw e;
                } catch (Exception e) {
                    NamingException ne = new NamingException(
                        "problem generating object using object factory");
                    ne.setRootCause(e);
                    throw ne;
                }
            } catch (CannotProceedException cpe) {
                javax.naming.Context cctx = getContinuationContext(cpe);
                return cctx.lookup(cpe.getRemainingName());
            }
    }

    /**
      * Performs bind or rebind in the context depending on whether the
      * flag rebind is set. The only objects allowed to be bound are of
      * types org.omg.CORBA.Object, org.omg.CosNaming.NamingContext.
      * You can use a state factory to turn other objects (such as
      * Remote) into these acceptable forms.
      *
      * Uses the COS Naming apis bind/rebind or
      * bind_context/rebind_context.
      * @param pth NameComponent[] object
      * @param obj Object to be bound.
      * @param rebind perform rebind ? if true performs a rebind.
      * @exception NotFound No objects under the name.
      * @exception CannotProceed Unable to obtain a continuation context
      * @exception AlreadyBound An object is already bound to this name.
      */
    private void callBindOrRebind(NameComponent[] pth, Name name,
        java.lang.Object obj, boolean rebind) throws NamingException {
            if (_nc == null)
                throw new ConfigurationException(
                    "Context does not have a corresponding NamingContext");
            try {
                // Call state factories to convert
                obj = NamingManager.getStateToBind(obj, name, this, _env);

                if (obj instanceof CNCtx) {
                    // Use naming context object reference
                    obj = ((CNCtx)obj)._nc;
                }

                if ( obj instanceof org.omg.CosNaming.NamingContext) {
                    NamingContext nobj =
                        NamingContextHelper.narrow((org.omg.CORBA.Object)obj);
                    if (rebind)
                        _nc.rebind_context(pth,nobj);
                    else
                        _nc.bind_context(pth,nobj);

                } else if (obj instanceof org.omg.CORBA.Object) {
                    if (rebind)
                        _nc.rebind(pth,(org.omg.CORBA.Object)obj);
                    else
                        _nc.bind(pth,(org.omg.CORBA.Object)obj);
                }
                else
                    throw new IllegalArgumentException(
                "Only instances of org.omg.CORBA.Object can be bound");
            } catch (BAD_PARAM e) {
                // probably narrow() failed?
                NamingException ne = new NotContextException(name.toString());
                ne.setRootCause(e);
                throw ne;
            } catch (Exception e) {
                throw ExceptionMapper.mapException(e, this, pth);
            }
    }

    /**
      * Converts the "Name" name into a NameComponent[] object and
      * performs the bind operation. Uses callBindOrRebind. Throws an
      * invalid name exception if the name is empty. We need a name to
      * bind the object even when we work within the current context.
      * @param name JNDI Name object
      * @param obj Object to be bound.
      * @exception NamingException See callBindOrRebind
      */
    public  void bind(Name name, java.lang.Object obj)
        throws NamingException {
            if (name.size() == 0 ) {
                throw new InvalidNameException("Name is empty");
            }

            if (debug) {
                System.out.println("Bind: " + name);
            }
            NameComponent[] path = CNNameParser.nameToCosName(name);

            try {
                callBindOrRebind(path, name, obj, false);
            } catch (CannotProceedException e) {
                javax.naming.Context cctx = getContinuationContext(e);
                cctx.bind(e.getRemainingName(), obj);
            }
    }

    static private javax.naming.Context
        getContinuationContext(CannotProceedException cpe)
        throws NamingException {
        try {
            return NamingManager.getContinuationContext(cpe);
        } catch (CannotProceedException e) {
            java.lang.Object resObj = e.getResolvedObj();
            if (resObj instanceof Reference) {
                Reference ref = (Reference)resObj;
                RefAddr addr = ref.get("nns");
                if (addr.getContent() instanceof javax.naming.Context) {
                    NamingException ne = new NameNotFoundException(
                        "No object reference bound for specified name");
                    ne.setRootCause(cpe.getRootCause());
                    ne.setRemainingName(cpe.getRemainingName());
                    throw ne;
                }
            }
            throw e;
        }
    }

    /**
      * Converts the "String" name into a CompositeName object and
      * performs the bind operation. Uses callBindOrRebind. Throws an
      * invalid name exception if the name is empty.
      * @param name string
      * @param obj Object to be bound.
      * @exception NamingException See callBindOrRebind
      */
    public void bind(String name, java.lang.Object obj) throws NamingException {
        bind(new CompositeName(name), obj);
    }

    /**
      * Converts the "Name" name into a NameComponent[] object and
      * performs the rebind operation. Uses callBindOrRebind. Throws an
      * invalid name exception if the name is empty. We must have a name
      * to rebind the object to even if we are working within the current
      * context.
      * @param name string
      * @param obj Object to be bound.
      * @exception NamingException See callBindOrRebind
      */
    public  void rebind(Name name, java.lang.Object obj)
        throws NamingException {
            if (name.size() == 0 ) {
                throw new InvalidNameException("Name is empty");
            }
            NameComponent[] path = CNNameParser.nameToCosName(name);
            try {
                callBindOrRebind(path, name, obj, true);
            } catch (CannotProceedException e) {
                javax.naming.Context cctx = getContinuationContext(e);
                cctx.rebind(e.getRemainingName(), obj);
            }
    }

    /**
      * Converts the "String" name into a CompositeName object and
      * performs the rebind operation. Uses callBindOrRebind. Throws an
      * invalid name exception if the name is an empty string.
      * @param name string
      * @param obj Object to be bound.
      * @exception NamingException See callBindOrRebind
      */
    public  void rebind(String name, java.lang.Object obj)
        throws NamingException {
            rebind(new CompositeName(name), obj);
    }

    /**
      * Calls the unbind api of COS Naming and uses the exception mapper
      * class  to map the exceptions
      * @param path NameComponent[] object
      * @exception NotFound No objects under the name. If leaf
      * is not found, that's OK according to the JNDI spec
      * @exception CannotProceed Unable to obtain a continuation context
      * @exception InvalidName Name not understood.
      */
    private void callUnbind(NameComponent[] path) throws NamingException {
            if (_nc == null)
                throw new ConfigurationException(
                    "Context does not have a corresponding NamingContext");
            try {
                _nc.unbind(path);
            } catch (NotFound e) {
                // If leaf is the one missing, return success
                // as per JNDI spec

                if (leafNotFound(e, path[path.length-1])) {
                    ; // do nothing
                } else {
                    throw ExceptionMapper.mapException(e, this, path);
                }
            } catch (Exception e) {
                throw ExceptionMapper.mapException(e, this, path);
            }
    }

    private boolean leafNotFound(NotFound e, NameComponent leaf) {

        // This test is not foolproof because some name servers
        // always just return one component in rest_of_name
        // so you might not be able to tell whether that is
        // the leaf (e.g. aa/aa/aa, which one is missing?)

        NameComponent rest;
        return e.why.value() == NotFoundReason._missing_node &&
            e.rest_of_name.length == 1 &&
            (rest=e.rest_of_name[0]).id.equals(leaf.id) &&
            (rest.kind == leaf.kind ||
             (rest.kind != null && rest.kind.equals(leaf.kind)));
    }

    /**
      * Converts the "String" name into a CompositeName object and
      * performs the unbind operation. Uses callUnbind. If the name is
      * empty, throws an invalid name exception. Do we unbind the
      * current context (JNDI spec says work with the current context if
      * the name is empty) ?
      * @param name string
      * @exception NamingException See callUnbind
      */
    public  void unbind(String name) throws NamingException {
        unbind(new CompositeName(name));
    }

    /**
      * Converts the "Name" name into a NameComponent[] object and
      * performs the unbind operation. Uses callUnbind. Throws an
      * invalid name exception if the name is empty.
      * @param name string
      * @exception NamingException See callUnbind
      */
    public  void unbind(Name name)
        throws NamingException {
            if (name.size() == 0 )
                throw new InvalidNameException("Name is empty");
            NameComponent[] path = CNNameParser.nameToCosName(name);
            try {
                callUnbind(path);
            } catch (CannotProceedException e) {
                javax.naming.Context cctx = getContinuationContext(e);
                cctx.unbind(e.getRemainingName());
            }
    }

    /**
      * Renames an object. Since COS Naming does not support a rename
      * api, this method unbinds the object with the "oldName" and
      * creates a new binding.
      * @param oldName string, existing name for the binding.
      * @param newName string, name used to replace.
      * @exception NamingException See bind
      */
    public  void rename(String oldName,String newName)
        throws NamingException {
            rename(new CompositeName(oldName), new CompositeName(newName));
    }

    /**
      * Renames an object. Since COS Naming does not support a rename
      * api, this method unbinds the object with the "oldName" and
      * creates a new binding.
      * @param oldName JNDI Name, existing name for the binding.
      * @param newName JNDI Name, name used to replace.
      * @exception NamingException See bind
      */
    public  void rename(Name oldName,Name newName)
        throws NamingException {
            if (_nc == null)
                throw new ConfigurationException(
                    "Context does not have a corresponding NamingContext");
            if (oldName.size() == 0 || newName.size() == 0)
                throw new InvalidNameException("One or both names empty");
            java.lang.Object obj = lookup(oldName);
            bind(newName,obj);
            unbind(oldName);
    }

    /**
      * Returns a NameClassEnumeration object which has a list of name
      * class pairs. Lists the current context if the name is empty.
      * @param name string
      * @exception NamingException All exceptions thrown by lookup
      * with a non-null argument
      * @return a list of name-class objects as a NameClassEnumeration.
      */
    public  NamingEnumeration list(String name) throws NamingException {
            return list(new CompositeName(name));
    }

    /**
      * Returns a NameClassEnumeration object which has a list of name
      * class pairs. Lists the current context if the name is empty.
      * @param name JNDI Name
      * @exception NamingException All exceptions thrown by lookup
      * @return a list of name-class objects as a NameClassEnumeration.
      */
    public  NamingEnumeration list(Name name)
        throws NamingException {
            return listBindings(name);
    }

    /**
      * Returns a BindingEnumeration object which has a list of name
      * object pairs. Lists the current context if the name is empty.
      * @param name string
      * @exception NamingException all exceptions returned by lookup
      * @return a list of bindings as a BindingEnumeration.
      */
    public  NamingEnumeration listBindings(String name)
        throws NamingException {
            return listBindings(new CompositeName(name));
    }

    /**
      * Returns a BindingEnumeration object which has a list of name
      * class pairs. Lists the current context if the name is empty.
      * @param name JNDI Name
      * @exception NamingException all exceptions returned by lookup.
      * @return a list of bindings as a BindingEnumeration.
      */
    public  NamingEnumeration listBindings(Name name)
        throws NamingException {
            if (_nc == null)
                throw new ConfigurationException(
                    "Context does not have a corresponding NamingContext");
            if (name.size() > 0) {
                try {
                    java.lang.Object obj = lookup(name);
                    if (obj instanceof CNCtx) {
                        return new CNBindingEnumeration(
                                        (CNCtx) obj, true, _env);
                    } else {
                        throw new NotContextException(name.toString());
                    }
                } catch (NamingException ne) {
                    throw ne;
                } catch (BAD_PARAM e) {
                    NamingException ne =
                        new NotContextException(name.toString());
                    ne.setRootCause(e);
                    throw ne;
                }
            }
            return new CNBindingEnumeration(this, false, _env);
    }

    /**
      * Calls the destroy on the COS Naming Server
      * @param nc The NamingContext object to use.
      * @exception NotEmpty when the context is not empty and cannot be destroyed.
      */
    private void callDestroy(NamingContext nc)
        throws NamingException {
            if (_nc == null)
                throw new ConfigurationException(
                    "Context does not have a corresponding NamingContext");
            try {
                nc.destroy();
            } catch (Exception e) {
                throw ExceptionMapper.mapException(e, this, null);
            }
    }

    /**
      * Uses the callDestroy function to destroy the context. If name is
      * empty destroys the current context.
      * @param name string
      * @exception OperationNotSupportedException when list is invoked
      * with a non-null argument
      */
    public  void destroySubcontext(String name) throws NamingException {
        destroySubcontext(new CompositeName(name));
    }

    /**
      * Uses the callDestroy function to destroy the context. Destroys
      * the current context if name is empty.
      * @param name JNDI Name
      * @exception OperationNotSupportedException when list is invoked
      * with a non-null argument
      */
    public  void destroySubcontext(Name name)
        throws NamingException {
            if (_nc == null)
                throw new ConfigurationException(
                    "Context does not have a corresponding NamingContext");
            NamingContext the_nc = _nc;
            NameComponent[] path = CNNameParser.nameToCosName(name);
            if ( name.size() > 0) {
                try {
                    javax.naming.Context ctx =
                        (javax.naming.Context) callResolve(path);
                    CNCtx cnc = (CNCtx)ctx;
                    the_nc = cnc._nc;
                    cnc.close(); //remove the reference to the context
                } catch (ClassCastException e) {
                    throw new NotContextException(name.toString());
                } catch (CannotProceedException e) {
                    javax.naming.Context cctx = getContinuationContext(e);
                    cctx.destroySubcontext(e.getRemainingName());
                    return;
                } catch (NameNotFoundException e) {
                    // If leaf is the one missing, return success
                    // as per JNDI spec

                    if (e.getRootCause() instanceof NotFound &&
                        leafNotFound((NotFound)e.getRootCause(),
                            path[path.length-1])) {
                        return; // leaf missing OK
                    }
                    throw e;
                } catch (NamingException e) {
                    throw e;
                }
            }
            callDestroy(the_nc);
            callUnbind(path);
    }

    /**
      * Calls the bind_new_context COS naming api to create a new subcontext.
      * @param path NameComponent[] object
      * @exception NotFound No objects under the name.
      * @exception CannotProceed Unable to obtain a continuation context
      * @exception InvalidName Name not understood.
      * @exception AlreadyBound An object is already bound to this name.
      * @return the new context object.
      */
    private javax.naming.Context callBindNewContext(NameComponent[] path)
        throws NamingException {
            if (_nc == null)
                throw new ConfigurationException(
                    "Context does not have a corresponding NamingContext");
            try {
                NamingContext nctx = _nc.bind_new_context(path);
                return new CNCtx(_orb, orbTracker, nctx, _env,
                                        makeFullName(path));
            } catch (Exception e) {
                throw ExceptionMapper.mapException(e, this, path);
            }
    }

    /**
      * Uses the callBindNewContext convenience function to create a new
      * context. Throws an invalid name exception if the name is empty.
      * @param name string
      * @exception NamingException See callBindNewContext
      * @return the new context object.
      */
    public  javax.naming.Context createSubcontext(String name)
        throws NamingException {
            return createSubcontext(new CompositeName(name));
    }

    /**
      * Uses the callBindNewContext convenience function to create a new
      * context. Throws an invalid name exception if the name is empty.
      * @param name string
      * @exception NamingException See callBindNewContext
      * @return the new context object.
      */
    public  javax.naming.Context createSubcontext(Name name)
        throws NamingException {
            if (name.size() == 0 )
                throw new InvalidNameException("Name is empty");
            NameComponent[] path = CNNameParser.nameToCosName(name);
            try {
                return callBindNewContext(path);
            } catch (CannotProceedException e) {
                javax.naming.Context cctx = getContinuationContext(e);
                return cctx.createSubcontext(e.getRemainingName());
            }
    }

    /**
      * Is mapped to resolve in the COS Naming api.
      * @param name string
      * @exception NamingException See lookup.
      * @return the resolved object.
      */
    public  java.lang.Object lookupLink(String name) throws NamingException {
            return lookupLink(new CompositeName(name));
    }

    /**
      * Is mapped to resolve in the COS Naming api.
      * @param name string
      * @exception NamingException See lookup.
      * @return the resolved object.
      */
    public  java.lang.Object lookupLink(Name name) throws NamingException {
            return lookup(name);
    }

    /**
      * Allow access to the name parser object.
      * @param String JNDI name, is ignored since there is only one Name
      * Parser object.
      * @exception NamingException --
      * @return NameParser object
      */
    public  NameParser getNameParser(String name) throws NamingException {
        return parser;
    }

    /**
      * Allow access to the name parser object.
      * @param Name JNDI name, is ignored since there is only one Name
      * Parser object.
      * @exception NamingException --
      * @return NameParser object
      */
    public  NameParser getNameParser(Name name) throws NamingException {
        return parser;
    }

    /**
      * Returns the current environment.
      * @return Environment.
      */
    public  Hashtable getEnvironment() throws NamingException {
        if (_env == null) {
            return new Hashtable(5, 0.75f);
        } else {
            return (Hashtable)_env.clone();
        }
    }

    public String composeName(String name, String prefix) throws NamingException {
        return composeName(new CompositeName(name),
            new CompositeName(prefix)).toString();
    }

    public Name composeName(Name name, Name prefix) throws NamingException {
        Name result = (Name)prefix.clone();
        return result.addAll(name);
    }

    /**
      * Adds to the environment for the current context.
      * Record change but do not reinitialize ORB.
      *
      * @param propName The property name.
      * @param propVal  The ORB.
      * @return the previous value of this property if any.
      */
    public java.lang.Object addToEnvironment(String propName,
        java.lang.Object propValue)
        throws NamingException {
            if (_env == null) {
                _env = new Hashtable(7, 0.75f);
            } else {
                // copy-on-write
                _env = (Hashtable)_env.clone();
            }

            return _env.put(propName, propValue);
    }

    // Record change but do not reinitialize ORB
    public java.lang.Object removeFromEnvironment(String propName)
        throws NamingException {
            if (_env != null  && _env.get(propName) != null) {
                // copy-on-write
                _env = (Hashtable)_env.clone();
                return _env.remove(propName);
            }
            return null;
    }

    synchronized public void incEnumCount() {
        enumCount++;
        if (debug) {
            System.out.println("incEnumCount, new count:" + enumCount);
        }
    }

    synchronized public void decEnumCount()
            throws NamingException {
        enumCount--;
        if (debug) {
            System.out.println("decEnumCount, new count:" + enumCount +
                        "    isCloseCalled:" + isCloseCalled);
        }
        if ((enumCount == 0) && isCloseCalled) {
            close();
        }
    }

    synchronized public void close() throws NamingException {

        if (enumCount > 0) {
            isCloseCalled = true;
            return;
        }

        // Never destroy an orb in CNCtx.
        // The orb we have is either the shared/default orb, or one passed in to a constructor
        // from elsewhere, so that orb is somebody else's reponsibility.
    }

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