/*
 * Copyright (c) 1999, 2002, 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.toolkit.dir;

import javax.naming.*;
import javax.naming.directory.*;
import javax.naming.spi.*;
import java.util.*;

/**
 * A sample service provider that implements a hierarchical directory in memory.
 * Every operation begins by doing a lookup on the name passed to it and then
 * calls a corresponding "do<OperationName>" on the result of the lookup. The
 * "do<OperationName>" does the work without any further resolution (it assumes
 * that it is the target context).
 */

public class HierMemDirCtx implements DirContext {

    static private final boolean debug = false;
    private static final NameParser defaultParser = new HierarchicalNameParser();

    protected Hashtable myEnv;
    protected Hashtable bindings;
    protected Attributes attrs;
    protected boolean ignoreCase = false;
    protected NamingException readOnlyEx = null;
    protected NameParser myParser = defaultParser;

    private boolean alwaysUseFactory;

    public void close() throws NamingException {
        myEnv = null;
        bindings = null;
        attrs = null;
    }

    public String getNameInNamespace() throws NamingException {
        throw new OperationNotSupportedException(
            "Cannot determine full name");
    }

    public HierMemDirCtx() {
        this(null, false, false);
    }

    public HierMemDirCtx(boolean ignoreCase) {
        this(null, ignoreCase, false);
    }

    public HierMemDirCtx(Hashtable environment, boolean ignoreCase) {
        this(environment, ignoreCase, false);
    }

    protected HierMemDirCtx(Hashtable environment, boolean ignoreCase,
        boolean useFac) {
        myEnv = environment;
        this.ignoreCase = ignoreCase;
        init();
        this.alwaysUseFactory = useFac;
    }

    private void init() {
        attrs = new BasicAttributes(ignoreCase);
        bindings = new Hashtable(11, 0.75f);
    }

    public Object lookup(String name) throws NamingException {
        return lookup(myParser.parse(name));
    }

    public Object lookup(Name name) throws NamingException {
        return doLookup(name, alwaysUseFactory);
    }

    public Object doLookup(Name name, boolean useFactory)
        throws NamingException {

        Object target = null;
        name = canonizeName(name);

        switch(name.size()) {
        case 0:
            // name is empty, caller wants this object
            target = this;
            break;

        case 1:
            // name is atomic, caller wants one of this object's bindings
            target = bindings.get(name);
            break;

        default:
            // name is compound, delegate to child context
            HierMemDirCtx ctx = (HierMemDirCtx)bindings.get(name.getPrefix(1));
            if(ctx == null) {
                target = null;
            } else {
                target = ctx.doLookup(name.getSuffix(1), false);
            }
            break;
        }

        if(target == null) {
            throw new NameNotFoundException(name.toString());
        }

        if (useFactory) {
            try {
                return DirectoryManager.getObjectInstance(target,
                    name, this, myEnv,
                    (target instanceof HierMemDirCtx) ?
                    ((HierMemDirCtx)target).attrs : null);
            } catch (NamingException e) {
                throw e;
            } catch (Exception e) {
                NamingException e2 = new NamingException(
                    "Problem calling getObjectInstance");
                e2.setRootCause(e);
                throw e2;
            }
        } else {
            return target;
        }
    }

    public void bind(String name, Object obj) throws NamingException {
        bind(myParser.parse(name), obj);
    }

    public void bind(Name name, Object obj) throws NamingException {
        doBind(name, obj, null, alwaysUseFactory);
    }

    public void bind(String name, Object obj, Attributes attrs)
            throws NamingException {
        bind(myParser.parse(name), obj, attrs);
    }

    public void bind(Name name, Object obj, Attributes attrs)
            throws NamingException {
        doBind(name, obj, attrs, alwaysUseFactory);
    }

    protected void doBind(Name name, Object obj, Attributes attrs,
        boolean useFactory) throws NamingException {
        if (name.isEmpty()) {
            throw new InvalidNameException("Cannot bind empty name");
        }

        if (useFactory) {
            DirStateFactory.Result res = DirectoryManager.getStateToBind(
                obj, name, this, myEnv, attrs);
            obj = res.getObject();
            attrs = res.getAttributes();
        }

        HierMemDirCtx ctx= (HierMemDirCtx) doLookup(getInternalName(name), false);
        ctx.doBindAux(getLeafName(name), obj);

        if (attrs != null && attrs.size() > 0) {
            modifyAttributes(name, ADD_ATTRIBUTE, attrs);
        }
    }

    protected void doBindAux(Name name, Object obj) throws NamingException {
        if (readOnlyEx != null) {
            throw (NamingException) readOnlyEx.fillInStackTrace();
        }

        if (bindings.get(name) != null) {
            throw new NameAlreadyBoundException(name.toString());
        }
        if(obj instanceof HierMemDirCtx) {
            bindings.put(name, obj);
        } else {
            throw new SchemaViolationException(
                "This context only supports binding objects of it's own kind");
        }
    }

    public void rebind(String name, Object obj) throws NamingException {
        rebind(myParser.parse(name), obj);
    }

    public void rebind(Name name, Object obj) throws NamingException {
        doRebind(name, obj, null, alwaysUseFactory);
    }

    public void rebind(String name, Object obj, Attributes attrs)
            throws NamingException {
        rebind(myParser.parse(name), obj, attrs);
    }

    public void rebind(Name name, Object obj, Attributes attrs)
            throws NamingException {
        doRebind(name, obj, attrs, alwaysUseFactory);
    }

    protected void doRebind(Name name, Object obj, Attributes attrs,
        boolean useFactory) throws NamingException {
        if (name.isEmpty()) {
            throw new InvalidNameException("Cannot rebind empty name");
        }

        if (useFactory) {
            DirStateFactory.Result res = DirectoryManager.getStateToBind(
                obj, name, this, myEnv, attrs);
            obj = res.getObject();
            attrs = res.getAttributes();
        }

        HierMemDirCtx ctx= (HierMemDirCtx) doLookup(getInternalName(name), false);
        ctx.doRebindAux(getLeafName(name), obj);

        //
        // attrs == null -> use attrs from obj
        // attrs != null -> use attrs
        //
        // %%% Strictly speaking, when attrs is non-null, we should
        // take the explicit step of removing obj's attrs.
        // We don't do that currently.

        if (attrs != null && attrs.size() > 0) {
            modifyAttributes(name, ADD_ATTRIBUTE, attrs);
        }
    }

    protected void doRebindAux(Name name, Object obj) throws NamingException {
        if (readOnlyEx != null) {
            throw (NamingException) readOnlyEx.fillInStackTrace();
        }
        if(obj instanceof HierMemDirCtx) {
            bindings.put(name, obj);

        } else {
            throw new SchemaViolationException(
                "This context only supports binding objects of it's own kind");
        }
    }

    public void unbind(String name) throws NamingException {
        unbind(myParser.parse(name));
    }

    public void unbind(Name name) throws NamingException {
        if (name.isEmpty()) {
            throw new InvalidNameException("Cannot unbind empty name");
        } else {
            HierMemDirCtx ctx=
                (HierMemDirCtx) doLookup(getInternalName(name), false);
            ctx.doUnbind(getLeafName(name));
        }
    }

    protected void doUnbind(Name name) throws NamingException {
        if (readOnlyEx != null) {
            throw (NamingException) readOnlyEx.fillInStackTrace();
        }

        bindings.remove(name);  // attrs will also be removed along with ctx
    }

    public void rename(String oldname, String newname)
            throws NamingException {
         rename(myParser.parse(oldname), myParser.parse(newname));
    }

    public void rename(Name oldname, Name newname)
            throws NamingException {

        if(newname.isEmpty() || oldname.isEmpty()) {
            throw new InvalidNameException("Cannot rename empty name");
        }

        if (!getInternalName(newname).equals(getInternalName(oldname))) {
            throw new InvalidNameException("Cannot rename across contexts");
        }

        HierMemDirCtx ctx =
            (HierMemDirCtx) doLookup(getInternalName(newname), false);
        ctx.doRename(getLeafName(oldname), getLeafName(newname));
    }

    protected void doRename(Name oldname, Name newname) throws NamingException {
        if (readOnlyEx != null) {
            throw (NamingException) readOnlyEx.fillInStackTrace();
        }

        oldname = canonizeName(oldname);
        newname = canonizeName(newname);

        // Check if new name exists
        if (bindings.get(newname) != null) {
            throw new NameAlreadyBoundException(newname.toString());
        }

        // Check if old name is bound
        Object oldBinding = bindings.remove(oldname);
        if (oldBinding == null) {
            throw new NameNotFoundException(oldname.toString());
        }

        bindings.put(newname, oldBinding);
    }

    public NamingEnumeration list(String name) throws NamingException {
        return list(myParser.parse(name));
    }

    public NamingEnumeration list(Name name) throws NamingException {
        HierMemDirCtx ctx = (HierMemDirCtx) doLookup(name, false);
        return ctx.doList();
    }

    protected NamingEnumeration doList () throws NamingException {
        return new FlatNames(bindings.keys());
    }


    public NamingEnumeration listBindings(String name) throws NamingException {
        return listBindings(myParser.parse(name));
    }

    public NamingEnumeration listBindings(Name name) throws NamingException {
        HierMemDirCtx ctx = (HierMemDirCtx)doLookup(name, false);
        return ctx.doListBindings(alwaysUseFactory);
    }

    protected NamingEnumeration doListBindings(boolean useFactory)
        throws NamingException {
        return new FlatBindings(bindings, myEnv, useFactory);
    }

    public void destroySubcontext(String name) throws NamingException {
        destroySubcontext(myParser.parse(name));
    }

    public void destroySubcontext(Name name) throws NamingException {
        HierMemDirCtx ctx =
            (HierMemDirCtx) doLookup(getInternalName(name), false);
        ctx.doDestroySubcontext(getLeafName(name));
    }

    protected void doDestroySubcontext(Name name) throws NamingException {

        if (readOnlyEx != null) {
            throw (NamingException) readOnlyEx.fillInStackTrace();
        }
        name = canonizeName(name);
        bindings.remove(name);
    }

    public Context createSubcontext(String name) throws NamingException {
        return createSubcontext(myParser.parse(name));
    }

    public Context createSubcontext(Name name) throws NamingException {
        return createSubcontext(name, null);
    }

    public DirContext createSubcontext(String name, Attributes attrs)
            throws NamingException {
        return createSubcontext(myParser.parse(name), attrs);
    }

    public DirContext createSubcontext(Name name, Attributes attrs)
            throws NamingException {
        HierMemDirCtx ctx =
            (HierMemDirCtx) doLookup(getInternalName(name), false);
        return ctx.doCreateSubcontext(getLeafName(name), attrs);
    }

    protected DirContext doCreateSubcontext(Name name, Attributes attrs)
        throws NamingException {
        if (readOnlyEx != null) {
            throw (NamingException) readOnlyEx.fillInStackTrace();
        }

        name = canonizeName(name);

        if (bindings.get(name) != null) {
            throw new NameAlreadyBoundException(name.toString());
        }
        HierMemDirCtx newCtx = createNewCtx();
        bindings.put(name, newCtx);
        if(attrs != null) {
            newCtx.modifyAttributes("", ADD_ATTRIBUTE, attrs);
        }
        return newCtx;
    }


    public Object lookupLink(String name) throws NamingException {
        // This context does not treat links specially
        return lookupLink(myParser.parse(name));
    }

    public Object lookupLink(Name name) throws NamingException {
        // Flat namespace; no federation; just call string version
        return lookup(name);
    }

    public NameParser getNameParser(String name) throws NamingException {
        return myParser;
    }

    public NameParser getNameParser(Name name) throws NamingException {
        return myParser;
    }

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

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

    public Object addToEnvironment(String propName, Object propVal)
            throws NamingException {
        myEnv = (myEnv == null) ?
            new Hashtable(11, 0.75f) : (Hashtable)myEnv.clone();

        return myEnv.put(propName, propVal);
    }

    public Object removeFromEnvironment(String propName)
            throws NamingException {
        if (myEnv == null)
            return null;

        myEnv = (Hashtable)myEnv.clone();
        return myEnv.remove(propName);
    }

    public Hashtable getEnvironment() throws NamingException {
        if (myEnv == null) {
            return new Hashtable(5, 0.75f);
        } else {
            return (Hashtable)myEnv.clone();
        }
    }

    public Attributes getAttributes(String name)
       throws NamingException {
       return getAttributes(myParser.parse(name));
    }

    public Attributes getAttributes(Name name)
        throws NamingException {
        HierMemDirCtx ctx = (HierMemDirCtx) doLookup(name, false);
        return ctx.doGetAttributes();
    }

    protected Attributes doGetAttributes() throws NamingException {
        return (Attributes)attrs.clone();
    }

    public Attributes getAttributes(String name, String[] attrIds)
        throws NamingException {
        return getAttributes(myParser.parse(name), attrIds);
    }

    public Attributes getAttributes(Name name, String[] attrIds)
        throws NamingException {
        HierMemDirCtx ctx = (HierMemDirCtx) doLookup(name, false);
        return ctx.doGetAttributes(attrIds);
    }

    protected Attributes doGetAttributes(String[] attrIds)
        throws NamingException {

        if (attrIds == null) {
            return doGetAttributes();
        }
        Attributes attrs = new BasicAttributes(ignoreCase);
        Attribute attr = null;
            for(int i=0; i<attrIds.length; i++) {
                attr = this.attrs.get(attrIds[i]);
                if (attr != null) {
                    attrs.put(attr);
                }
            }
        return attrs;
    }

    public void modifyAttributes(String name, int mod_op, Attributes attrs)
        throws NamingException   {
        modifyAttributes(myParser.parse(name), mod_op, attrs);
    }

    public void modifyAttributes(Name name, int mod_op, Attributes attrs)
        throws NamingException {

        if (attrs == null || attrs.size() == 0) {
            throw new IllegalArgumentException(
                "Cannot modify without an attribute");
        }

        // turn it into a modification Enumeration and pass it on
        NamingEnumeration attrEnum = attrs.getAll();
        ModificationItem[] mods = new ModificationItem[attrs.size()];
        for (int i = 0; i < mods.length && attrEnum.hasMoreElements(); i++) {
            mods[i] = new ModificationItem(mod_op, (Attribute)attrEnum.next());
        }

        modifyAttributes(name, mods);
    }

    public void modifyAttributes(String name, ModificationItem[] mods)
        throws NamingException   {
        modifyAttributes(myParser.parse(name), mods);
    }

    public void modifyAttributes(Name name, ModificationItem[] mods)
        throws NamingException {
        HierMemDirCtx ctx = (HierMemDirCtx) doLookup(name, false);
        ctx.doModifyAttributes(mods);
    }

    protected void doModifyAttributes(ModificationItem[] mods)
        throws NamingException {

        if (readOnlyEx != null) {
            throw (NamingException) readOnlyEx.fillInStackTrace();
        }

        applyMods(mods, attrs);
    }

    protected static Attributes applyMods(ModificationItem[] mods,
        Attributes orig) throws NamingException {

        ModificationItem mod;
        Attribute existingAttr, modAttr;
        NamingEnumeration modVals;

        for (int i = 0; i < mods.length; i++) {
            mod = mods[i];
            modAttr = mod.getAttribute();

            switch(mod.getModificationOp()) {
            case ADD_ATTRIBUTE:
                if (debug) {
                    System.out.println("HierMemDSCtx: adding " +
                                       mod.getAttribute().toString());
                }
                existingAttr = orig.get(modAttr.getID());
                if (existingAttr == null) {
                    orig.put((Attribute)modAttr.clone());
                } else {
                    // Add new attribute values to existing attribute
                    modVals = modAttr.getAll();
                    while (modVals.hasMore()) {
                        existingAttr.add(modVals.next());
                    }
                }
                break;
            case REPLACE_ATTRIBUTE:
                if (modAttr.size() == 0) {
                    orig.remove(modAttr.getID());
                } else {
                    orig.put((Attribute)modAttr.clone());
                }
                break;
            case REMOVE_ATTRIBUTE:
                existingAttr = orig.get(modAttr.getID());
                if (existingAttr != null) {
                    if (modAttr.size() == 0) {
                        orig.remove(modAttr.getID());
                    } else {
                        // Remove attribute values from existing attribute
                        modVals = modAttr.getAll();
                        while (modVals.hasMore()) {
                            existingAttr.remove(modVals.next());
                        }
                        if (existingAttr.size() == 0) {
                            orig.remove(modAttr.getID());
                        }
                    }
                }
                break;
            default:
                throw new AttributeModificationException("Unknown mod_op");
            }
        }

        return orig;
    }

    public NamingEnumeration search(String name,
                                    Attributes matchingAttributes)
        throws NamingException {
        return search(name, matchingAttributes, null);
    }

    public NamingEnumeration search(Name name,
                                    Attributes matchingAttributes)
        throws NamingException {
            return search(name, matchingAttributes, null);
    }

     public NamingEnumeration search(String name,
                                    Attributes matchingAttributes,
                                    String[] attributesToReturn)
        throws NamingException {
        return search(myParser.parse(name), matchingAttributes,
            attributesToReturn);
    }

     public NamingEnumeration search(Name name,
                                    Attributes matchingAttributes,
                                    String[] attributesToReturn)
         throws NamingException {

        HierMemDirCtx target = (HierMemDirCtx) doLookup(name, false);

        SearchControls cons = new SearchControls();
        cons.setReturningAttributes(attributesToReturn);

        return new LazySearchEnumerationImpl(
            target.doListBindings(false),
            new ContainmentFilter(matchingAttributes),
            cons, this, myEnv,
            false); // alwaysUseFactory ignored because objReturnFlag == false
    }

    public NamingEnumeration search(Name name,
                                    String filter,
                                    SearchControls cons)
        throws NamingException {
        DirContext target = (DirContext) doLookup(name, false);

        SearchFilter stringfilter = new SearchFilter(filter);
        return new LazySearchEnumerationImpl(
            new HierContextEnumerator(target,
                (cons != null) ? cons.getSearchScope() :
                SearchControls.ONELEVEL_SCOPE),
            stringfilter,
            cons, this, myEnv, alwaysUseFactory);
    }

     public NamingEnumeration search(Name name,
                                    String filterExpr,
                                    Object[] filterArgs,
                                    SearchControls cons)
            throws NamingException {

        String strfilter = SearchFilter.format(filterExpr, filterArgs);
        return search(name, strfilter, cons);
    }

    public NamingEnumeration search(String name,
                                    String filter,
                                    SearchControls cons)
        throws NamingException {
        return search(myParser.parse(name), filter, cons);
    }

    public NamingEnumeration search(String name,
                                    String filterExpr,
                                    Object[] filterArgs,
                                    SearchControls cons)
            throws NamingException {
        return search(myParser.parse(name), filterExpr, filterArgs, cons);
    }

    // This function is called whenever a new object needs to be created.
    // this is used so that if anyone subclasses us, they can override this
    // and return object of their own kind.
    protected HierMemDirCtx createNewCtx() throws NamingException {
        return new HierMemDirCtx(myEnv, ignoreCase);
    }

    // If the supplied name is a composite name, return the name that
    // is its first component.
    protected Name canonizeName(Name name) throws NamingException {
        Name canonicalName = name;

        if(!(name instanceof HierarchicalName)) {
            // If name is not of the correct type, make copy
            canonicalName = new HierarchicalName();
            int n = name.size();
            for(int i = 0; i < n; i++) {
                canonicalName.add(i, name.get(i));
            }
        }

        return canonicalName;
    }

     protected Name getInternalName(Name name) throws NamingException {
         return (name.getPrefix(name.size() - 1));
     }

     protected Name getLeafName(Name name) throws NamingException {
         return (name.getSuffix(name.size() - 1));
     }


     public DirContext getSchema(String name) throws NamingException {
        throw new OperationNotSupportedException();
    }

     public DirContext getSchema(Name name) throws NamingException {
        throw new OperationNotSupportedException();
    }

     public DirContext getSchemaClassDefinition(String name)
        throws NamingException {
        throw new OperationNotSupportedException();
    }

    public DirContext getSchemaClassDefinition(Name name)
            throws NamingException {
        throw new OperationNotSupportedException();
    }

    // Set context in readonly mode; throw e when update operation attempted.
    public void setReadOnly(NamingException e) {
        readOnlyEx = e;
    }

    // Set context to support case-insensitive names
    public void setIgnoreCase(boolean ignoreCase) {
        this.ignoreCase = ignoreCase;
    }

    public void setNameParser(NameParser parser) {
        myParser = parser;
    }

    // Class for enumerating name/class pairs
    private class FlatNames implements NamingEnumeration {
        Enumeration names;

        FlatNames (Enumeration names) {
            this.names = names;
        }

        public boolean hasMoreElements() {
            try {
                return hasMore();
            } catch (NamingException e) {
                return false;
            }
        }

        public boolean hasMore() throws NamingException {
            return names.hasMoreElements();
        }

        public Object nextElement() {
            try {
                return next();
            } catch (NamingException e) {
                throw new NoSuchElementException(e.toString());
            }
        }

        public Object next() throws NamingException {
            Name name = (Name)names.nextElement();
            String className = bindings.get(name).getClass().getName();
            return new NameClassPair(name.toString(), className);
        }

        public void close() {
            names = null;
        }
    }

   // Class for enumerating bindings
    private final class FlatBindings extends FlatNames {
        private Hashtable bds;
        private Hashtable env;
        private boolean useFactory;

        FlatBindings(Hashtable bindings, Hashtable env, boolean useFactory) {
            super(bindings.keys());
            this.env = env;
            this.bds = bindings;
            this.useFactory = useFactory;
        }

        public Object next() throws NamingException {
            Name name = (Name)names.nextElement();

            HierMemDirCtx obj = (HierMemDirCtx)bds.get(name);

            Object answer = obj;
            if (useFactory) {
                Attributes attrs = obj.getAttributes(""); // only method available
                try {
                    answer = DirectoryManager.getObjectInstance(obj,
                        name, HierMemDirCtx.this, env, attrs);
                } catch (NamingException e) {
                    throw e;
                } catch (Exception e) {
                    NamingException e2 = new NamingException(
                        "Problem calling getObjectInstance");
                    e2.setRootCause(e);
                    throw e2;
                }
            }

            return new Binding(name.toString(), answer);
        }
    }

    public class HierContextEnumerator extends ContextEnumerator {
        public HierContextEnumerator(Context context, int scope)
            throws NamingException {
                super(context, scope);
        }

        protected HierContextEnumerator(Context context, int scope,
            String contextName, boolean returnSelf) throws NamingException {
            super(context, scope, contextName, returnSelf);
        }

        protected NamingEnumeration getImmediateChildren(Context ctx)
            throws NamingException {
                return ((HierMemDirCtx)ctx).doListBindings(false);
        }

        protected ContextEnumerator newEnumerator(Context ctx, int scope,
            String contextName, boolean returnSelf) throws NamingException {
                return new HierContextEnumerator(ctx, scope, contextName,
                    returnSelf);
        }
    }
}

    // CompundNames's HashCode() method isn't good enough for many string.
    // The only prupose of this subclass is to have a more discerning
    // hash function. We'll make up for the performance hit by caching
    // the hash value.

final class HierarchicalName extends CompoundName {
    private int hashValue = -1;

    // Creates an empty name
    HierarchicalName() {
        super(new Enumeration() {
            public boolean hasMoreElements() {return false;}
            public Object nextElement() {throw new NoSuchElementException();}
        },
            HierarchicalNameParser.mySyntax);
    }

    HierarchicalName(Enumeration comps, Properties syntax) {
        super(comps, syntax);
    }

    HierarchicalName(String n, Properties syntax) throws InvalidNameException {
        super(n, syntax);
    }

    // just like String.hashCode, only it pays no attention to length
    public int hashCode() {
        if (hashValue == -1) {

            String name = toString().toUpperCase();
            int len = name.length();
            int off = 0;
            char val[] = new char[len];

            name.getChars(0, len, val, 0);

            for (int i = len; i > 0; i--) {
                hashValue = (hashValue * 37) + val[off++];
            }
        }

        return hashValue;
    }

    public Name getPrefix(int posn) {
        Enumeration comps = super.getPrefix(posn).getAll();
        return (new HierarchicalName(comps, mySyntax));
    }

    public Name getSuffix(int posn) {
        Enumeration comps = super.getSuffix(posn).getAll();
        return (new HierarchicalName(comps, mySyntax));
    }

    public Object clone() {
        return (new HierarchicalName(getAll(), mySyntax));
    }

    private static final long serialVersionUID = -6717336834584573168L;
}

// This is the default name parser (used if setNameParser is not called)
final class HierarchicalNameParser implements NameParser {
    static final Properties mySyntax = new Properties();
    static {
        mySyntax.put("jndi.syntax.direction", "left_to_right");
        mySyntax.put("jndi.syntax.separator", "/");
        mySyntax.put("jndi.syntax.ignorecase", "true");
        mySyntax.put("jndi.syntax.escape", "\\");
        mySyntax.put("jndi.syntax.beginquote", "\"");
        //mySyntax.put("jndi.syntax.separator.ava", "+");
        //mySyntax.put("jndi.syntax.separator.typeval", "=");
        mySyntax.put("jndi.syntax.trimblanks", "false");
    };

    public Name parse(String name) throws NamingException {
        return new HierarchicalName(name, mySyntax);
    }
}
