//
//  ========================================================================
//  Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
//  ------------------------------------------------------------------------
//  All rights reserved. This program and the accompanying materials
//  are made available under the terms of the Eclipse Public License v1.0
//  and Apache License v2.0 which accompanies this distribution.
//
//      The Eclipse Public License is available at
//      http://www.eclipse.org/legal/epl-v10.html
//
//      The Apache License v2.0 is available at
//      http://www.opensource.org/licenses/apache2.0.php
//
//  You may elect to redistribute this code under either of these licenses.
//  ========================================================================
//

package org.eclipse.jetty.jndi;


import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;

import javax.naming.Binding;
import javax.naming.CompoundName;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.LinkRef;
import javax.naming.Name;
import javax.naming.NameAlreadyBoundException;
import javax.naming.NameNotFoundException;
import javax.naming.NameParser;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.NotContextException;
import javax.naming.OperationNotSupportedException;
import javax.naming.Reference;
import javax.naming.Referenceable;
import javax.naming.spi.NamingManager;

import org.eclipse.jetty.util.component.Dumpable;
import org.eclipse.jetty.util.log.Logger;


/*------------------------------------------------*/
/** NamingContext
 * <p>Implementation of Context interface.
 *
 * <p><h4>Notes</h4>
 * <p>All Names are expected to be Compound, not Composite.
 */
@SuppressWarnings("unchecked")
public class NamingContext implements Context, Cloneable, Dumpable
{
    private final static Logger __log=NamingUtil.__log;
    private final static List<Binding> __empty = Collections.emptyList();
    public static final String DEEP_BINDING = "org.eclipse.jetty.jndi.deepBinding";
    public static final String LOCK_PROPERTY = "org.eclipse.jetty.jndi.lock";
    public static final String UNLOCK_PROPERTY = "org.eclipse.jetty.jndi.unlock";

    protected final Hashtable<String,Object> _env = new Hashtable<String,Object>();
    private boolean _supportDeepBinding = false;
    protected Map<String,Binding> _bindings = new HashMap<String,Binding>();

    protected NamingContext _parent = null;
    protected String _name = null;
    protected NameParser _parser = null;
    private Collection<Listener> _listeners;

    /*------------------------------------------------*/
    /**
     * Naming Context Listener.
     */
    public interface Listener
    {
        /**
         * Called by {@link NamingContext#addBinding(Name, Object)} when adding
         * a binding.
         * @param ctx The context to add to.
         * @param binding The binding to add.
         * @return The binding to bind, or null if the binding should be ignored.
         */
        Binding bind(NamingContext ctx, Binding binding);

        /**
         * @param ctx The context to unbind from
         * @param binding The binding that was unbound.
         */
        void unbind(NamingContext ctx, Binding binding);
    }

    /*------------------------------------------------*/
    /**
     * Constructor
     *
     * @param env environment properties
     * @param name relative name of this context
     * @param parent immediate ancestor Context (can be null)
     * @param parser NameParser for this Context
     */
    public NamingContext(Hashtable<String,Object> env,
                         String name,
                         NamingContext parent,
                         NameParser parser)
    {
        if (env != null)
        {
            _env.putAll(env);
            // look for deep binding support in _env
            Object support = _env.get(DEEP_BINDING);
            if (support == null)
                _supportDeepBinding = false;
            else
                _supportDeepBinding = support != null?Boolean.parseBoolean(support.toString()):false;
        }
        else
        {
            // no env?  likely this is a root context (java or local) that
            // was created without an _env.  Look for a system property.
            String value = System.getProperty(DEEP_BINDING,"false");
            _supportDeepBinding = Boolean.parseBoolean(value);
            // put what we discovered into the _env for later sub-contexts
            // to utilize.
            _env.put(DEEP_BINDING,_supportDeepBinding);
        }
        _name = name;
        _parent = parent;
        _parser = parser;
        if(__log.isDebugEnabled())
            __log.debug("supportDeepBinding={}",_supportDeepBinding);
    }


    /*------------------------------------------------*/
    /**
     * Clone this NamingContext
     *
     * @return copy of this NamingContext
     * @exception CloneNotSupportedException if an error occurs
     */
    public Object clone ()
        throws CloneNotSupportedException
    {
        NamingContext ctx = (NamingContext)super.clone();
        ctx._env.putAll(_env);
        ctx._bindings.putAll(_bindings);
        return ctx;
    }


    /*------------------------------------------------*/
    /**
     * Getter for _name
     *
     * @return name of this Context (relative, not absolute)
     */
    public String getName ()
    {
        return _name;
    }

    /*------------------------------------------------*/
    /**
     * Getter for _parent
     *
     * @return parent Context
     */
    public Context getParent()
    {
        return _parent;
    }

    /*------------------------------------------------*/
    /**
     * Setter for _parser
     *
     *
     */
    public void setNameParser (NameParser parser)
    {
        _parser = parser;
    }


    public final void setEnv (Hashtable<String,Object> env)
    {
        _env.clear();
        if(env == null)
            return;
        _env.putAll(env);
        _supportDeepBinding = _env.containsKey(DEEP_BINDING);
    }


    public Map<String,Binding> getBindings ()
    {
        return _bindings;
    }

    public void setBindings(Map<String,Binding> bindings)
    {
        _bindings = bindings;
    }

    /*------------------------------------------------*/
    /**
     * Bind a name to an object
     *
     * @param name Name of the object
     * @param obj object to bind
     * @exception NamingException if an error occurs
     */
    public void bind(Name name, Object obj)
        throws NamingException
    {
        if (isLocked())
            throw new NamingException ("This context is immutable");

        Name cname = toCanonicalName(name);

        if (cname == null)
            throw new NamingException ("Name is null");

        if (cname.size() == 0)
            throw new NamingException ("Name is empty");


        //if no subcontexts, just bind it
        if (cname.size() == 1)
        {
            //get the object to be bound
            Object objToBind = NamingManager.getStateToBind(obj, name,this, _env);
            // Check for Referenceable
            if (objToBind instanceof Referenceable)
            {
                objToBind = ((Referenceable)objToBind).getReference();
            }

            //anything else we should be able to bind directly
            addBinding (cname, objToBind);
        }
        else
        {
            if(__log.isDebugEnabled())__log.debug("Checking for existing binding for name="+cname+" for first element of name="+cname.get(0));

            //walk down the subcontext hierarchy
            //need to ignore trailing empty "" name components

            String firstComponent = cname.get(0);
            Object ctx = null;

            if (firstComponent.equals(""))
                ctx = this;
            else
            {

                Binding  binding = getBinding (firstComponent);
                if (binding == null) {
                    if (_supportDeepBinding)
                    {
                        Name subname = _parser.parse(firstComponent);
                        Context subctx = new NamingContext((Hashtable)_env.clone(),firstComponent,this,_parser);
                        addBinding(subname,subctx);
                        binding = getBinding(subname);
                    }
                    else
                    {
                        throw new NameNotFoundException(firstComponent + " is not bound");
                    }
                }

                ctx = binding.getObject();

                if (ctx instanceof Reference)
                {
                    //deference the object
                    try
                    {
                        ctx = NamingManager.getObjectInstance(ctx, getNameParser("").parse(firstComponent), this, _env);
                    }
                    catch (NamingException e)
                    {
                        throw e;
                    }
                    catch (Exception e)
                    {
                        __log.warn("",e);
                        throw new NamingException (e.getMessage());
                    }
                }
            }


            if (ctx instanceof Context)
            {
                ((Context)ctx).bind (cname.getSuffix(1), obj);
            }
            else
                throw new NotContextException ("Object bound at "+firstComponent +" is not a Context");
        }
    }



    /*------------------------------------------------*/
    /**
     * Bind a name (as a String) to an object
     *
     * @param name a <code>String</code> value
     * @param obj an <code>Object</code> value
     * @exception NamingException if an error occurs
     */
    public void bind(String name, Object obj)
        throws NamingException
    {
        bind (_parser.parse(name), obj);
    }


    /*------------------------------------------------*/
    /**
     * Create a context as a child of this one
     *
     * @param name a <code>Name</code> value
     * @return a <code>Context</code> value
     * @exception NamingException if an error occurs
     */
    public Context createSubcontext (Name name)
        throws NamingException
    {
        if (isLocked())
        {
            NamingException ne = new NamingException ("This context is immutable");
            ne.setRemainingName(name);
            throw ne;
        }

        Name cname = toCanonicalName (name);

        if (cname == null)
            throw new NamingException ("Name is null");
        if (cname.size() == 0)
            throw new NamingException ("Name is empty");

        if (cname.size() == 1)
        {
            //not permitted to bind if something already bound at that name
            Binding binding = getBinding (cname);
            if (binding != null)
                throw new NameAlreadyBoundException (cname.toString());

            Context ctx = new NamingContext ((Hashtable)_env.clone(), cname.get(0), this, _parser);
            addBinding (cname, ctx);
            return ctx;
        }


        //If the name has multiple subcontexts, walk the hierarchy by
        //fetching the first one. All intermediate subcontexts in the
        //name must already exist.
        String firstComponent = cname.get(0);
        Object ctx = null;

        if (firstComponent.equals(""))
            ctx = this;
        else
        {
            Binding binding = getBinding (firstComponent);
            if (binding == null)
                throw new NameNotFoundException (firstComponent + " is not bound");

            ctx = binding.getObject();

            if (ctx instanceof Reference)
            {
                //deference the object
                if(__log.isDebugEnabled())__log.debug("Object bound at "+firstComponent +" is a Reference");
                try
                {
                    ctx = NamingManager.getObjectInstance(ctx, getNameParser("").parse(firstComponent), this, _env);
                }
                catch (NamingException e)
                {
                    throw e;
                }
                catch (Exception e)
                {
                    __log.warn("",e);
                    throw new NamingException (e.getMessage());
                }
            }
        }

        if (ctx instanceof Context)
        {
            return ((Context)ctx).createSubcontext (cname.getSuffix(1));
        }
        else
            throw new NotContextException (firstComponent +" is not a Context");
    }


    /*------------------------------------------------*/
    /**
     * Create a Context as a child of this one
     *
     * @param name a <code>String</code> value
     * @return a <code>Context</code> value
     * @exception NamingException if an error occurs
     */
    public Context createSubcontext (String name)
        throws NamingException
    {
        return createSubcontext(_parser.parse(name));
    }



    /*------------------------------------------------*/
    /**
     *
     *
     * @param name name of subcontext to remove
     * @exception NamingException if an error occurs
     */
    public void destroySubcontext (String name)
        throws NamingException
    {
        removeBinding(_parser.parse(name));
    }



    /*------------------------------------------------*/
    /**
     *
     *
     * @param name name of subcontext to remove
     * @exception NamingException if an error occurs
     */
    public void destroySubcontext (Name name)
        throws NamingException
    {
         removeBinding(name);
    }

    /*------------------------------------------------*/
    /**
     * Lookup a binding by name
     *
     * @param name name of bound object
     * @exception NamingException if an error occurs
     */
    public Object lookup(Name name)
        throws NamingException
    {
        if(__log.isDebugEnabled())__log.debug("Looking up name=\""+name+"\"");
        Name cname = toCanonicalName(name);

        if ((cname == null) || (cname.size() == 0))
        {
            __log.debug("Null or empty name, returning copy of this context");
            NamingContext ctx = new NamingContext (_env, _name, _parent, _parser);
            ctx._bindings=_bindings;
            return ctx;
        }



        if (cname.size() == 1)
        {
            Binding binding = getBinding (cname);
            if (binding == null)
            {
                NameNotFoundException nnfe = new NameNotFoundException();
                nnfe.setRemainingName(cname);
                throw nnfe;
            }


            Object o = binding.getObject();

            //handle links by looking up the link
            if (o instanceof LinkRef)
            {
                //if link name starts with ./ it is relative to current context
                String linkName = ((LinkRef)o).getLinkName();
                if (linkName.startsWith("./"))
                    return this.lookup (linkName.substring(2));
                else
                {
                    //link name is absolute
                    InitialContext ictx = new InitialContext();
                    return ictx.lookup (linkName);
                }
            }
            else if (o instanceof Reference)
            {
                //deference the object
                try
                {
                    return NamingManager.getObjectInstance(o, cname, this, _env);
                }
                catch (NamingException e)
                {
                    throw e;
                }
                catch (Exception e)
                {
                    __log.warn("",e);
                    throw new NamingException (e.getMessage());
                }
            }
            else
                return o;
        }

        //it is a multipart name, recurse to the first subcontext

        String firstComponent = cname.get(0);
        Object ctx = null;

        if (firstComponent.equals(""))
            ctx = this;
        else
        {

            Binding binding = getBinding (firstComponent);
            if (binding == null)
            {
                NameNotFoundException nnfe = new NameNotFoundException();
                nnfe.setRemainingName(cname);
                throw nnfe;
            }

            //as we have bound a reference to an object factory
            //for the component specific contexts
            //at "comp" we need to resolve the reference
            ctx = binding.getObject();

            if (ctx instanceof Reference)
            {
                //deference the object
                try
                {
                    ctx = NamingManager.getObjectInstance(ctx, getNameParser("").parse(firstComponent), this, _env);
                }
                catch (NamingException e)
                {
                    throw e;
                }
                catch (Exception e)
                {
                    __log.warn("",e);
                    throw new NamingException (e.getMessage());
                }
            }
        }
        if (!(ctx instanceof Context))
            throw new NotContextException();

        return ((Context)ctx).lookup (cname.getSuffix(1));
    }


    /*------------------------------------------------*/
    /**
     * Lookup binding of an object by name
     *
     * @param name name of bound object
     * @return object bound to name
     * @exception NamingException if an error occurs
     */
    public Object lookup (String name)
        throws NamingException
    {
        return lookup (_parser.parse(name));
    }



    /*------------------------------------------------*/
    /**
     * Lookup link bound to name
     *
     * @param name name of link binding
     * @return LinkRef or plain object bound at name
     * @exception NamingException if an error occurs
     */
    public Object lookupLink (Name name)
        throws NamingException
    {
        Name cname = toCanonicalName(name);

        if (cname == null)
        {
            NamingContext ctx = new NamingContext (_env, _name, _parent, _parser);
            ctx._bindings=_bindings;
            return ctx;
        }
        if (cname.size() == 0)
            throw new NamingException ("Name is empty");

        if (cname.size() == 1)
        {
            Binding binding = getBinding (cname);
            if (binding == null)
                throw new NameNotFoundException();

            Object o = binding.getObject();

            //handle links by looking up the link
            if (o instanceof Reference)
            {
                //deference the object
                try
                {
                    return NamingManager.getObjectInstance(o, cname.getPrefix(1), this, _env);
                }
                catch (NamingException e)
                {
                    throw e;
                }
                catch (Exception e)
                {
                    __log.warn("",e);
                    throw new NamingException (e.getMessage());
                }
            }
            else
            {
                //object is either a LinkRef which we don't dereference
                //or a plain object in which case spec says we return it
                return o;
            }
        }


        //it is a multipart name, recurse to the first subcontext
        String firstComponent = cname.get(0);
        Object ctx = null;

        if (firstComponent.equals(""))
            ctx = this;
        else
        {
            Binding binding = getBinding (firstComponent);
            if (binding == null)
                throw new NameNotFoundException ();

            ctx = binding.getObject();

            if (ctx instanceof Reference)
            {
                //deference the object
                try
                {
                    ctx = NamingManager.getObjectInstance(ctx, getNameParser("").parse(firstComponent), this, _env);
                }
                catch (NamingException e)
                {
                    throw e;
                }
                catch (Exception e)
                {
                    __log.warn("",e);
                    throw new NamingException (e.getMessage());
                }
            }
        }

        if (!(ctx instanceof Context))
            throw new NotContextException();

        return ((Context)ctx).lookup (cname.getSuffix(1));
    }


    /*------------------------------------------------*/
    /**
     * Lookup link bound to name
     *
     * @param name name of link binding
     * @return LinkRef or plain object bound at name
     * @exception NamingException if an error occurs
     */
    public Object lookupLink (String name)
        throws NamingException
    {
        return lookupLink (_parser.parse(name));
    }


    /*------------------------------------------------*/
    /**
     * List all names bound at Context named by Name
     *
     * @param name a <code>Name</code> value
     * @return a <code>NamingEnumeration</code> value
     * @exception NamingException if an error occurs
     */
    public NamingEnumeration list(Name name)
        throws NamingException
    {
        if(__log.isDebugEnabled())__log.debug("list() on Context="+getName()+" for name="+name);
        Name cname = toCanonicalName(name);



        if (cname == null)
        {
            return new NameEnumeration(__empty.iterator());
        }


        if (cname.size() == 0)
        {
           return new NameEnumeration (_bindings.values().iterator());
        }



        //multipart name
        String firstComponent = cname.get(0);
        Object ctx = null;

        if (firstComponent.equals(""))
            ctx = this;
        else
        {
            Binding binding = getBinding (firstComponent);
            if (binding == null)
                throw new NameNotFoundException ();

            ctx = binding.getObject();

            if (ctx instanceof Reference)
            {
                //deference the object
                if(__log.isDebugEnabled())__log.debug("Dereferencing Reference for "+name.get(0));
                try
                {
                    ctx = NamingManager.getObjectInstance(ctx, getNameParser("").parse(firstComponent), this, _env);
                }
                catch (NamingException e)
                {
                    throw e;
                }
                catch (Exception e)
                {
                    __log.warn("",e);
                    throw new NamingException (e.getMessage());
                }
            }
        }

        if (!(ctx instanceof Context))
            throw new NotContextException();

        return ((Context)ctx).list (cname.getSuffix(1));
    }


    /*------------------------------------------------*/
    /**
     * List all names bound at Context named by Name
     *
     * @param name a <code>Name</code> value
     * @return a <code>NamingEnumeration</code> value
     * @exception NamingException if an error occurs
     */
    public NamingEnumeration list(String name)
        throws NamingException
    {
        return list(_parser.parse(name));
    }



    /*------------------------------------------------*/
    /**
     * List all Bindings present at Context named by Name
     *
     * @param name a <code>Name</code> value
     * @return a <code>NamingEnumeration</code> value
     * @exception NamingException if an error occurs
     */
    public NamingEnumeration listBindings(Name name)
        throws NamingException
    {
        Name cname = toCanonicalName (name);

        if (cname == null)
        {
            return new BindingEnumeration(__empty.iterator());
        }

        if (cname.size() == 0)
        {
           return new BindingEnumeration (_bindings.values().iterator());
        }



        //multipart name
        String firstComponent = cname.get(0);
        Object ctx = null;

        //if a name has a leading "/" it is parsed as "" so ignore it by staying
        //at this level in the tree
        if (firstComponent.equals(""))
            ctx = this;
        else
        {
            //it is a non-empty name component
            Binding binding = getBinding (firstComponent);
            if (binding == null)
                throw new NameNotFoundException ();

            ctx = binding.getObject();

            if (ctx instanceof Reference)
            {
                //deference the object
                try
                {
                    ctx = NamingManager.getObjectInstance(ctx, getNameParser("").parse(firstComponent), this, _env);
                }
                catch (NamingException e)
                {
                    throw e;
                }
                catch (Exception e)
                {
                    __log.warn("",e);
                    throw new NamingException (e.getMessage());
                }
            }
        }

        if (!(ctx instanceof Context))
            throw new NotContextException();

        return ((Context)ctx).listBindings (cname.getSuffix(1));
    }



    /*------------------------------------------------*/
    /**
     * List all Bindings at Name
     *
     * @param name a <code>String</code> value
     * @return a <code>NamingEnumeration</code> value
     * @exception NamingException if an error occurs
     */
    public NamingEnumeration listBindings(String name)
        throws NamingException
    {
        return listBindings (_parser.parse(name));
    }


    /*------------------------------------------------*/
    /**
     * Overwrite or create a binding
     *
     * @param name a <code>Name</code> value
     * @param obj an <code>Object</code> value
     * @exception NamingException if an error occurs
     */
    public void rebind(Name name,
                       Object obj)
        throws NamingException
    {
        if (isLocked())
            throw new NamingException ("This context is immutable");

        Name cname = toCanonicalName(name);

        if (cname == null)
            throw new NamingException ("Name is null");

        if (cname.size() == 0)
            throw new NamingException ("Name is empty");


        //if no subcontexts, just bind it
        if (cname.size() == 1)
        {
            //check if it is a Referenceable
            Object objToBind = NamingManager.getStateToBind(obj, name, this, _env);

            if (objToBind instanceof Referenceable)
            {
                objToBind = ((Referenceable)objToBind).getReference();
            }
            removeBinding(cname);
            addBinding (cname, objToBind);
        }
        else
        {
            //walk down the subcontext hierarchy
            if(__log.isDebugEnabled())__log.debug("Checking for existing binding for name="+cname+" for first element of name="+cname.get(0));

            String firstComponent = cname.get(0);
            Object ctx = null;


            if (firstComponent.equals(""))
                ctx = this;
            else
            {
                Binding  binding = getBinding (name.get(0));
                if (binding == null)
                    throw new NameNotFoundException (name.get(0)+ " is not bound");

                ctx = binding.getObject();


                if (ctx instanceof Reference)
                {
                    //deference the object
                    try
                    {
                        ctx = NamingManager.getObjectInstance(ctx, getNameParser("").parse(firstComponent), this, _env);
                    }
                    catch (NamingException e)
                    {
                        throw e;
                    }
                    catch (Exception e)
                    {
                        __log.warn("",e);
                        throw new NamingException (e.getMessage());
                    }
                }
            }

            if (ctx instanceof Context)
            {
                ((Context)ctx).rebind (cname.getSuffix(1), obj);
            }
            else
                throw new NotContextException ("Object bound at "+firstComponent +" is not a Context");
        }
    }


    /*------------------------------------------------*/
    /**
     * Overwrite or create a binding from Name to Object
     *
     * @param name a <code>String</code> value
     * @param obj an <code>Object</code> value
     * @exception NamingException if an error occurs
     */
    public void rebind (String name,
                        Object obj)
        throws NamingException
    {
        rebind (_parser.parse(name), obj);
    }

    /*------------------------------------------------*/
    /**
     * Not supported.
     *
     * @param name a <code>String</code> value
     * @exception NamingException if an error occurs
     */
    public void unbind (String name)
        throws NamingException
    {
        unbind(_parser.parse(name));
    }

    /*------------------------------------------------*/
    /**
     * Not supported.
     *
     * @param name a <code>String</code> value
     * @exception NamingException if an error occurs
     */
    public void unbind (Name name)
        throws NamingException
    {
        if (name.size() == 0)
            return;


        if (isLocked())
            throw new NamingException ("This context is immutable");

        Name cname = toCanonicalName(name);

        if (cname == null)
            throw new NamingException ("Name is null");

        if (cname.size() == 0)
            throw new NamingException ("Name is empty");


        //if no subcontexts, just unbind it
        if (cname.size() == 1)
        {
            removeBinding (cname);
        }
        else
        {
            //walk down the subcontext hierarchy
            if(__log.isDebugEnabled())__log.debug("Checking for existing binding for name="+cname+" for first element of name="+cname.get(0));

            String firstComponent = cname.get(0);
            Object ctx = null;


            if (firstComponent.equals(""))
                ctx = this;
            else
            {
                Binding  binding = getBinding (name.get(0));
                if (binding == null)
                    throw new NameNotFoundException (name.get(0)+ " is not bound");

                ctx = binding.getObject();

                if (ctx instanceof Reference)
                {
                    //deference the object
                    try
                    {
                        ctx = NamingManager.getObjectInstance(ctx, getNameParser("").parse(firstComponent), this, _env);
                    }
                    catch (NamingException e)
                    {
                        throw e;
                    }
                    catch (Exception e)
                    {
                        __log.warn("",e);
                        throw new NamingException (e.getMessage());
                    }
                }
            }

            if (ctx instanceof Context)
            {
                ((Context)ctx).unbind (cname.getSuffix(1));
            }
            else
                throw new NotContextException ("Object bound at "+firstComponent +" is not a Context");
        }
    }

    /*------------------------------------------------*/
    /**
     * Not supported
     *
     * @param oldName a <code>Name</code> value
     * @param newName a <code>Name</code> value
     * @exception NamingException if an error occurs
     */
    public void rename(Name oldName,
                       Name newName)
        throws NamingException
    {
        throw new OperationNotSupportedException();
    }


    /*------------------------------------------------*/
    /**
     * Not supported
     *
     * @param oldName a <code>Name</code> value
     * @param newName a <code>Name</code> value
     * @exception NamingException if an error occurs
     */    public void rename(String oldName,
                              String newName)
     throws NamingException
     {
         throw new OperationNotSupportedException();
     }



    /*------------------------------------------------*/
    /** Join two names together. These are treated as
     * CompoundNames.
     *
     * @param name a <code>Name</code> value
     * @param prefix a <code>Name</code> value
     * @return a <code>Name</code> value
     * @exception NamingException if an error occurs
     */
    public Name composeName(Name name,
                            Name prefix)
        throws NamingException
    {
        if (name == null)
            throw new NamingException ("Name cannot be null");
        if (prefix == null)
            throw new NamingException ("Prefix cannot be null");

        Name compoundName = (CompoundName)prefix.clone();
        compoundName.addAll (name);
        return compoundName;
    }



    /*------------------------------------------------*/
    /** Join two names together. These are treated as
     * CompoundNames.
     *
     * @param name a <code>Name</code> value
     * @param prefix a <code>Name</code> value
     * @return a <code>Name</code> value
     * @exception NamingException if an error occurs
     */
    public String composeName (String name,
                               String prefix)
        throws NamingException
    {
        if (name == null)
            throw new NamingException ("Name cannot be null");
        if (prefix == null)
            throw new NamingException ("Prefix cannot be null");

        Name compoundName = _parser.parse(prefix);
        compoundName.add (name);
        return compoundName.toString();
    }


    /*------------------------------------------------*/
    /**
     * Do nothing
     *
     * @exception NamingException if an error occurs
     */
    public void close ()
        throws NamingException
    {
    }


    /*------------------------------------------------*/
    /**
     * Return a NameParser for this Context.
     *
     * @param name a <code>Name</code> value
     * @return a <code>NameParser</code> value
     */
    public NameParser getNameParser (Name name)
    {
        return _parser;
    }

    /*------------------------------------------------*/
    /**
     * Return a NameParser for this Context.
     *
     * @param name a <code>Name</code> value
     * @return a <code>NameParser</code> value
     */
    public NameParser getNameParser (String name)
    {
        return _parser;
    }


    /*------------------------------------------------*/
    /**
     * Get the full name of this Context node
     * by visiting it's ancestors back to root.
     *
     * NOTE: if this Context has a URL namespace then
     * the URL prefix will be missing
     *
     * @return the full name of this Context
     * @exception NamingException if an error occurs
     */
    public String getNameInNamespace ()
        throws NamingException
    {
        Name name = _parser.parse("");

        NamingContext c = this;
        while (c != null)
        {
            String str = c.getName();
            if (str != null)
                name.add(0, str);
            c = (NamingContext)c.getParent();
        }
        return name.toString();
    }


    /*------------------------------------------------*/
    /**
     * Add an environment setting to this Context
     *
     * @param propName name of the property to add
     * @param propVal value of the property to add
     * @return propVal or previous value of the property
     * @exception NamingException if an error occurs
     */
    public Object addToEnvironment(String propName,
                                   Object propVal)
        throws NamingException
    {
        if (isLocked() && !(propName.equals(UNLOCK_PROPERTY)))
            throw new NamingException ("This context is immutable");

        return _env.put (propName, propVal);
    }


    /*------------------------------------------------*/
    /**
     * Remove a property from this Context's environment.
     *
     * @param propName name of property to remove
     * @return value of property or null if it didn't exist
     * @exception NamingException if an error occurs
     */
    public Object removeFromEnvironment(String propName)
        throws NamingException
    {
        if (isLocked())
            throw new NamingException ("This context is immutable");

        return _env.remove (propName);
    }


    /*------------------------------------------------*/
    /**
     * Get the environment of this Context.
     *
     * @return a copy of the environment of this Context.
     */
    public Hashtable getEnvironment ()
    {
        return (Hashtable)_env.clone();
    }

    /*------------------------------------------------*/
    /**
     * Add a name to object binding to this Context.
     *
     * @param name a <code>Name</code> value
     * @param obj an <code>Object</code> value
     */
    public void addBinding (Name name, Object obj) throws NameAlreadyBoundException
    {
        String key = name.toString();
        Binding binding=new Binding (key, obj);

        Collection<Listener> list = findListeners();

        for (Listener listener : list)
        {
            binding=listener.bind(this,binding);
            if (binding==null)
                break;
        }

        if(__log.isDebugEnabled())
            __log.debug("Adding binding with key="+key+" obj="+obj+" for context="+_name+" as "+binding);

        if (binding!=null)
        {
            if (_bindings.containsKey(key)) {
                if(_supportDeepBinding) {
                    // quietly return (no exception)
                    // this is jndi spec breaking, but is added to support broken
                    // jndi users like openejb.
                    return;
                }
                throw new NameAlreadyBoundException(name.toString());
            }
            _bindings.put(key,binding);
        }
    }

    /*------------------------------------------------*/
    /**
     * Get a name to object binding from this Context
     *
     * @param name a <code>Name</code> value
     * @return a <code>Binding</code> value
     */
    public Binding getBinding (Name name)
    {
        return (Binding) _bindings.get(name.toString());
    }


    /*------------------------------------------------*/
    /**
     * Get a name to object binding from this Context
     *
     * @param name as a String
     * @return null or the Binding
     */
    public Binding getBinding (String name)
    {
        return (Binding) _bindings.get(name);
    }

    /*------------------------------------------------*/
    public void removeBinding (Name name)
    {
        String key = name.toString();
        if (__log.isDebugEnabled())
            __log.debug("Removing binding with key="+key);
        Binding binding = _bindings.remove(key);
        if (binding!=null)
        {
            Collection<Listener> list = findListeners();
            for (Listener listener : list)
                listener.unbind(this,binding);
        }
    }

    /*------------------------------------------------*/
    /**
     * Remove leading or trailing empty components from
     * name. Eg "/comp/env/" -> "comp/env"
     *
     * @param name the name to normalize
     * @return normalized name
     */
    public Name toCanonicalName (Name name)
    {
        Name canonicalName = name;

        if (name != null)
        {
            if (canonicalName.size() > 1)
            {
                if (canonicalName.get(0).equals(""))
                    canonicalName = canonicalName.getSuffix(1);

                if (canonicalName.get(canonicalName.size()-1).equals(""))
                    canonicalName = canonicalName.getPrefix(canonicalName.size()-1);
            }
        }

        return canonicalName;
    }

    /* ------------------------------------------------------------ */
    public boolean isLocked()
    {
       if ((_env.get(LOCK_PROPERTY) == null) && (_env.get(UNLOCK_PROPERTY) == null))
           return false;

       Object lockKey = _env.get(LOCK_PROPERTY);
       Object unlockKey = _env.get(UNLOCK_PROPERTY);

       if ((lockKey != null) && (unlockKey != null) && (lockKey.equals(unlockKey)))
           return false;
       return true;
    }


    /* ------------------------------------------------------------ */
    public String dump()
    {
        StringBuilder buf = new StringBuilder();
        try
        {
            dump(buf,"");
        }
        catch(Exception e)
        {
            __log.warn(e);
        }
        return buf.toString();
    }


    /* ------------------------------------------------------------ */
    public void dump(Appendable out,String indent) throws IOException
    {
        out.append(this.getClass().getSimpleName()).append("@").append(Long.toHexString(this.hashCode())).append("\n");
        int size=_bindings.size();
        int i=0;
        for (Map.Entry<String,Binding> entry : ((Map<String,Binding>)_bindings).entrySet())
        {
            boolean last=++i==size;
            out.append(indent).append(" +- ").append(entry.getKey()).append(": ");

            Binding binding = entry.getValue();
            Object value = binding.getObject();

            if ("comp".equals(entry.getKey()) && value instanceof Reference && "org.eclipse.jetty.jndi.ContextFactory".equals(((Reference)value).getFactoryClassName()))
            {
                ContextFactory.dump(out,indent+(last?"    ":" |  "));
            }
            else if (value instanceof Dumpable)
            {
                ((Dumpable)value).dump(out,indent+(last?"    ":" |  "));
            }
            else
            {
                out.append(value.getClass().getSimpleName()).append("=");
                out.append(String.valueOf(value).replace('\n','|').replace('\r','|'));
                out.append("\n");
            }
        }
    }

    private Collection<Listener> findListeners()
    {
        Collection<Listener> list = new ArrayList<Listener>();
        NamingContext ctx=this;
        while (ctx!=null)
        {
            if (ctx._listeners!=null)
                list.addAll(ctx._listeners);
            ctx=(NamingContext)ctx.getParent();
        }
        return list;
    }

    public void addListener(Listener listener)
    {
        if (_listeners==null)
            _listeners=new ArrayList<Listener>();
        _listeners.add(listener);
    }

    public boolean removeListener(Listener listener)
    {
        return _listeners.remove(listener);
    }
    
    @Override
    public String toString()
    {
        StringBuilder buf = new StringBuilder();
        buf.append(this.getClass().getName()).append('@').append(Integer.toHexString(this.hashCode()));
        buf.append("[name=").append(this._name);
        buf.append(",parent=");
        if (this._parent != null)
        {
            buf.append(this._parent.getClass().getName()).append('@').append(Integer.toHexString(this._parent.hashCode()));
        }
        buf.append(",bindings");
        if (this._bindings == null)
        {
            buf.append("=<null>");
        }
        else
        {
            buf.append(".size=").append(this._bindings.size());
        }
        buf.append(']');
        return buf.toString();
    }
}
