/*
 * Copyright 1999-2004 Sun Microsystems, Inc.  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.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package com.sun.jndi.toolkit.ctx;

import java.util.Hashtable;

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

/**
  * Provides implementation of p_* operations using
  * c_* operations provided by subclasses.
  *
  * Clients: deal only with names for its own naming service.  Must
  * provide implementations for c_* methods, and for p_parseComponent()
  * and the c_*_nns methods if the defaults are not appropriate.
  *
  * @author Rosanna Lee
  * @author Scott Seligman
  */

public abstract class ComponentContext extends PartialCompositeContext {
    private static int debug = 0;

    protected ComponentContext() {
        _contextType = _COMPONENT;
    }

// ------ Abstract methods whose implementation are provided by subclass

    /* Equivalent methods in Context interface */
    protected abstract Object c_lookup(Name name, Continuation cont)
        throws NamingException;
    protected abstract Object c_lookupLink(Name name, Continuation cont)
        throws NamingException;

    protected abstract NamingEnumeration c_list(Name name,
        Continuation cont) throws NamingException;
    protected abstract NamingEnumeration c_listBindings(Name name,
        Continuation cont) throws NamingException;
    protected abstract void c_bind(Name name, Object obj, Continuation cont)
        throws NamingException;
    protected abstract void c_rebind(Name name, Object obj, Continuation cont)
        throws NamingException;
    protected abstract void c_unbind(Name name, Continuation cont)
        throws NamingException;
    protected abstract void c_destroySubcontext(Name name, Continuation cont)
        throws NamingException;
    protected abstract Context c_createSubcontext(Name name,
        Continuation cont) throws NamingException;
    protected abstract void c_rename(Name oldname, Name newname,
        Continuation cont) throws NamingException;
    protected abstract NameParser c_getNameParser(Name name, Continuation cont)
        throws NamingException;

// ------ Methods that may need to be overridden by subclass

    /* Parsing method */
    /**
      * Determines which of the first components of 'name' belong
      * to this naming system.
      * If no components belong to this naming system, return
      * the empty name (new CompositeName()) as the head,
      * and the entire name as the tail.
      *
      * The default implementation supports strong separation.
      * If the name is empty or if the first component is empty,
      * head is the empty name and tail is the entire name.
      * (This means that this context does not have any name to work with).
      * Otherwise, it returns the first component as head, and the rest of
      * the components as tail.
      *
      * Subclass should override this method according its own policies.
      *
      * For example, a weakly separated system with dynamic boundary
      * determination would simply return as head 'name'.
      * A weakly separated with static boundary
      * determination would select the components in the front of 'name'
      * that conform to some syntax rules.  (e.g. in X.500 syntax, perhaps
      * select front components that have a equal sign).
      * If none conforms, return an empty name.
      */
    protected HeadTail p_parseComponent(Name name, Continuation cont)
        throws NamingException {
        int separator;
        // if no name to parse, or if we're already at boundary
        if (name.isEmpty() ||  name.get(0).equals("")) {
            separator = 0;
        } else {
            separator = 1;
        }
        Name head, tail;

        if (name instanceof CompositeName) {
            head = name.getPrefix(separator);
            tail = name.getSuffix(separator);
        } else {
            // treat like compound name
            head = new CompositeName().add(name.toString());
            tail = null;
        }

        if (debug > 2) {
            System.err.println("ORIG: " + name);
            System.err.println("PREFIX: " + name);
            System.err.println("SUFFIX: " + null);
        }
        return new HeadTail(head, tail);
    }


    /* Resolution method for supporting federation */

    /**
      * Resolves the nns for 'name' when the named context is acting
      * as an intermediate context.
      *
      * For a system that supports only junctions, this would be
      * equilvalent to
      *         c_lookup(name, cont);
      * because for junctions, an intermediate slash simply signifies
      * a syntactic separator.
      *
      * For a system that supports only implicit nns, this would be
      * equivalent to
      *         c_lookup_nns(name, cont);
      * because for implicit nns, a slash always signifies the implicit nns,
      * regardless of whether it is intermediate or trailing.
      *
      * By default this method supports junctions, and also allows for an
      * implicit nns to be dynamically determined through the use of the
      * "nns" reference (see c_processJunction_nns()).
      * Contexts that implement implicit nns directly should provide an
      * appropriate override.
      *
      * A junction, by definition, is a binding of a name in one
      * namespace to an object in another.  The default implementation
      * of this method detects the crossover into another namespace
      * using the following heuristic:  there is a junction when "name"
      * resolves to a context that is not an instance of
      * this.getClass().  Contexts supporting junctions for which this
      * heuristic is inappropriate should override this method.
      */
    protected Object c_resolveIntermediate_nns(Name name, Continuation cont)
        throws NamingException {
            try {
                final Object obj = c_lookup(name, cont);

                // Do not append "" to Continuation 'cont' even if set
                // because the intention is to ignore the nns

                if (obj != null && getClass().isInstance(obj)) {
                    // If "obj" is in the same type as this object, it must
                    // not be a junction. Continue the lookup with "/".

                    cont.setContinueNNS(obj, name, this);
                    return null;

                } else if (obj != null && !(obj instanceof Context)) {
                    // obj is not even a context, so try to find its nns
                    // dynamically by constructing a Reference containing obj.
                    RefAddr addr = new RefAddr("nns") {
                        public Object getContent() {
                            return obj;
                        }
                        private static final long serialVersionUID =
                            -8831204798861786362L;
                    };
                    Reference ref = new Reference("java.lang.Object", addr);

                    // Resolved name has trailing slash to indicate nns
                    CompositeName resName = (CompositeName)name.clone();
                    resName.add(""); // add trailing slash

                    // Set continuation leave it to
                    // PartialCompositeContext.getPCContext() to throw CPE.
                    // Do not use setContinueNNS() because we've already
                    // consumed "/" (i.e., moved it to resName).

                    cont.setContinue(ref, resName, this);
                    return null;
                } else {
                    // Consume "/" and continue
                    return obj;
                }

            } catch (NamingException e) {
                e.appendRemainingComponent(""); // add nns back
                throw e;
            }
        }

    /* Equivalent of Context Methods for supporting nns */

    // The following methods are called when the Context methods
    // are invoked with a name that has a trailing slash.
    // For naming systems that support implicit nns,
    // the trailing slash signifies the implicit nns.
    // For such naming systems, override these c_*_nns methods.
    //
    // For naming systems that do not support implicit nns, the
    // default implementations here throw an exception.  See
    // c_processJunction_nns() for details.

    protected Object c_lookup_nns(Name name, Continuation cont)
        throws NamingException {
            c_processJunction_nns(name, cont);
            return null;
        }

    protected Object c_lookupLink_nns(Name name, Continuation cont)
        throws NamingException {
            c_processJunction_nns(name, cont);
            return null;
        }

    protected NamingEnumeration c_list_nns(Name name,
        Continuation cont) throws NamingException {
            c_processJunction_nns(name, cont);
            return null;
        }

    protected NamingEnumeration c_listBindings_nns(Name name,
        Continuation cont) throws NamingException {
            c_processJunction_nns(name, cont);
            return null;
        }

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

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

    protected void c_unbind_nns(Name name, Continuation cont)
        throws NamingException {
            c_processJunction_nns(name, cont);
        }

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

    protected void c_destroySubcontext_nns(Name name, Continuation cont)
        throws NamingException {
            c_processJunction_nns(name, cont);
        }


    protected void c_rename_nns(Name oldname, Name newname, Continuation cont)
        throws NamingException {
            c_processJunction_nns(oldname, cont);
        }

    protected NameParser c_getNameParser_nns(Name name, Continuation cont)
        throws NamingException {
            c_processJunction_nns(name, cont);
            return null;
        }

// ------ internal method used by ComponentContext

    /**
     * Locates the nns using the default policy.  This policy fully
     * handles junctions, but otherwise throws an exception when an
     * attempt is made to resolve an implicit nns.
     *
     * The default policy is as follows:  If there is a junction in
     * the namespace, then resolve to the junction and continue the
     * operation there (thus deferring to that context to find its own
     * nns).  Otherwise, resolve as far as possible and then throw
     * CannotProceedException with the resolved object being a reference:
     * the address type is "nns", and the address contents is this
     * context.
     *
     * For example, when c_bind_nns(name, obj, ...) is invoked, the
     * caller is attempting to bind the object "obj" to the nns of
     * "name".  If "name" is a junction, it names an object in another
     * naming system that (presumably) has an nns.  c_bind_nns() will
     * first resolve "name" to a context and then attempt to continue
     * the bind operation there, (thus binding to the nns of the
     * context named by "name").  If "name" is empty then throw an
     * exception, since this context does not by default support an
     * implicit nns.
     *
     * To implement a context that does support an implicit nns, it is
     * necessary to override this default policy.  This is done by
     * overriding the c_*_nns() methods (which each call this method
     * by default).
     */
    protected void c_processJunction_nns(Name name, Continuation cont)
            throws NamingException
    {
        if (name.isEmpty()) {
            // Construct a new Reference that contains this context.
            RefAddr addr = new RefAddr("nns") {
                public Object getContent() {
                    return ComponentContext.this;
                }
                private static final long serialVersionUID =
                    -1389472957988053402L;
            };
            Reference ref = new Reference("java.lang.Object", addr);

            // Set continuation leave it to PartialCompositeContext.getPCContext()
            // to throw the exception.
            // Do not use setContinueNNS() because we've are
            // setting relativeResolvedName to "/".
            cont.setContinue(ref, _NNS_NAME, this);
            return;
        }

        try {
            // lookup name to continue operation in nns
            Object target = c_lookup(name, cont);
            if (cont.isContinue())
                cont.appendRemainingComponent("");
            else {
                cont.setContinueNNS(target, name, this);
            }
        } catch (NamingException e) {
            e.appendRemainingComponent(""); // add nns back
            throw e;
        }
    }

    protected static final byte USE_CONTINUATION = 1;
    protected static final byte TERMINAL_COMPONENT = 2;
    protected static final byte TERMINAL_NNS_COMPONENT = 3;

    /**
      * Determine whether 'name' is a terminal component in
      * this naming system.
      * If so, return status indicating so, so that caller
      * can perform context operation on this name.
      *
      * If not, then the first component(s) of 'name' names
      * an intermediate context.  In that case, resolve these components
      * and set Continuation to be the object named.
      *
      * see test cases at bottom of file.
      */

    protected HeadTail p_resolveIntermediate(Name name, Continuation cont)
        throws NamingException {
        int ret = USE_CONTINUATION;
        cont.setSuccess();      // initialize
        HeadTail p = p_parseComponent(name, cont);
        Name tail = p.getTail();
        Name head = p.getHead();

        if (tail == null || tail.isEmpty()) {
//System.out.println("terminal : " + head);
            ret = TERMINAL_COMPONENT;
        } else if (!tail.get(0).equals("")) {
            // tail does not begin with "/"
/*
            if (head.isEmpty()) {
                // Context could not find name that it can use
                // illegal syntax error or name not found
//System.out.println("nnf exception : " + head);
                NamingException e = new NameNotFoundException();
                cont.setError(this, name);
                throw cont.fillInException(e);
            } else  {
*/
                // head is being used as intermediate context,
                // resolve head and set Continuation with tail
                try {
                    Object obj = c_resolveIntermediate_nns(head, cont);
//System.out.println("resInter : " + head + "=" + obj);
                    if (obj != null)
                        cont.setContinue(obj, head, this, tail);
                    else if (cont.isContinue()) {
                        checkAndAdjustRemainingName(cont.getRemainingName());
                        cont.appendRemainingName(tail);
                    }
                } catch (NamingException e) {
                    checkAndAdjustRemainingName(e.getRemainingName());
                    e.appendRemainingName(tail);
                    throw e;
                }
/*
            }
*/
        } else {
            // tail begins with "/"
            if (tail.size() == 1) {
                ret = TERMINAL_NNS_COMPONENT;
//System.out.println("terminal_nns : " + head);
            } else if (head.isEmpty() || isAllEmpty(tail)) {
                // resolve nns of head and continue with tail.getSuffix(1)
                Name newTail = tail.getSuffix(1);
                try {
                    Object obj = c_lookup_nns(head, cont);
//System.out.println("lookup_nns : " + head + "=" + obj);
                    if (obj != null)
                        cont.setContinue(obj, head, this, newTail);
                    else if (cont.isContinue()) {
                        cont.appendRemainingName(newTail);
//                      Name rname = cont.getRemainingName();
//System.out.println("cont.rname" + rname);
                    }
                } catch (NamingException e) {
                    e.appendRemainingName(newTail);
                    throw e;
                }
            } else {
                // head is being used as intermediate context
                // resolve and set continuation to tail
                try {
                    Object obj = c_resolveIntermediate_nns(head, cont);
//System.out.println("resInter2 : " + head + "=" + obj);
                    if (obj != null)
                        cont.setContinue(obj, head, this, tail);
                    else if (cont.isContinue()) {
                        checkAndAdjustRemainingName(cont.getRemainingName());
                        cont.appendRemainingName(tail);
                    }
                } catch (NamingException e) {
                    checkAndAdjustRemainingName(e.getRemainingName());
                    e.appendRemainingName(tail);
                    throw e;
                }
            }
        }

        p.setStatus(ret);
        return p;
    }

    // When c_resolveIntermediate_nns() or c_lookup_nns() sets up
    // its continuation, to indicate "nns", it appends an empty
    // component to the remaining name (e.g. "eng/"). If last
    // component of remaining name is empty; delete empty component
    // before appending tail so that composition of the names work
    // correctly. For example, when merging "eng/" and "c.b.a", we want
    // the result to be "eng/c.b.a" because the trailing slash in eng
    // is extraneous.  When merging "" and "c.b.a", we want the result
    // to be "/c.b.a" and so must keep the trailing slash (empty name).
    void checkAndAdjustRemainingName(Name rname) throws InvalidNameException {
        int count;
        if (rname != null && (count=rname.size()) > 1 &&
            rname.get(count-1).equals("")) {
            rname.remove(count-1);
        }
    }

    // Returns true if n contains only empty components
    protected boolean isAllEmpty(Name n) {
        int count = n.size();
        for (int i =0; i < count; i++ ) {
            if (!n.get(i).equals("")) {
                return false;
            }
        }
        return true;
    }



// ------ implementations of p_ Resolver and Context methods using
// ------ corresponding c_ and c_*_nns methods


    /* implementation for Resolver method */

    protected ResolveResult p_resolveToClass(Name name,
                                             Class contextType,
                                             Continuation cont)
            throws NamingException {

        if (contextType.isInstance(this)) {
            cont.setSuccess();
            return (new ResolveResult(this, name));
        }

        ResolveResult ret = null;
        HeadTail res = p_resolveIntermediate(name, cont);
        switch (res.getStatus()) {
        case TERMINAL_NNS_COMPONENT:
            Object obj = p_lookup(name, cont);
            if (!cont.isContinue() && contextType.isInstance(obj)) {
                ret = new ResolveResult(obj, _EMPTY_NAME);
            }
            break;

        case TERMINAL_COMPONENT:
            cont.setSuccess();  // no contextType found; return null
            break;

        default:
            /* USE_CONTINUATION */
            /* pcont already set or exception thrown */
            break;
        }
        return ret;
    }

    /* implementations of p_ Context methods */

    protected Object p_lookup(Name name, Continuation cont) throws NamingException {
        Object ret = null;
        HeadTail res = p_resolveIntermediate(name, cont);
        switch (res.getStatus()) {
            case TERMINAL_NNS_COMPONENT:
                ret = c_lookup_nns(res.getHead(), cont);
                if (ret instanceof LinkRef) {
                    cont.setContinue(ret, res.getHead(), this);
                    ret = null;
                }
                break;

            case TERMINAL_COMPONENT:
                ret = c_lookup(res.getHead(), cont);
                if (ret instanceof LinkRef) {
                    cont.setContinue(ret, res.getHead(), this);
                    ret = null;
                }
                break;

            default:
                /* USE_CONTINUATION */
                /* pcont already set or exception thrown */
                break;
        }
        return ret;
    }

    protected NamingEnumeration p_list(Name name, Continuation cont)
        throws NamingException {
        NamingEnumeration ret = null;
        HeadTail res = p_resolveIntermediate(name, cont);
        switch (res.getStatus()) {
            case TERMINAL_NNS_COMPONENT:
                if (debug > 0)
                    System.out.println("c_list_nns(" + res.getHead() + ")");
                ret = c_list_nns(res.getHead(), cont);
                break;

            case TERMINAL_COMPONENT:
                if (debug > 0)
                    System.out.println("c_list(" + res.getHead() + ")");
                ret = c_list(res.getHead(), cont);
                break;

            default:
                /* USE_CONTINUATION */
                /* cont already set or exception thrown */
                break;
        }
        return ret;
    }

    protected NamingEnumeration p_listBindings(Name name, Continuation cont) throws
        NamingException {
        NamingEnumeration ret = null;
        HeadTail res = p_resolveIntermediate(name, cont);
        switch (res.getStatus()) {
            case TERMINAL_NNS_COMPONENT:
                ret = c_listBindings_nns(res.getHead(), cont);
                break;

            case TERMINAL_COMPONENT:
                ret = c_listBindings(res.getHead(), cont);
                break;

            default:
                /* USE_CONTINUATION */
                /* cont already set or exception thrown */
                break;
        }
        return ret;
    }

    protected void p_bind(Name name, Object obj, Continuation cont) throws
        NamingException {
        HeadTail res = p_resolveIntermediate(name, cont);
        switch (res.getStatus()) {
            case TERMINAL_NNS_COMPONENT:
                c_bind_nns(res.getHead(), obj, cont);
                break;

            case TERMINAL_COMPONENT:
                c_bind(res.getHead(), obj, cont);
                break;

            default:
                /* USE_CONTINUATION */
                /* cont already set or exception thrown */
                break;
        }
    }

    protected void p_rebind(Name name, Object obj, Continuation cont) throws
        NamingException {
        HeadTail res = p_resolveIntermediate(name, cont);
        switch (res.getStatus()) {
            case TERMINAL_NNS_COMPONENT:
                c_rebind_nns(res.getHead(), obj, cont);
                break;

            case TERMINAL_COMPONENT:
                c_rebind(res.getHead(), obj, cont);
                break;

            default:
                /* USE_CONTINUATION */
                /* cont already set or exception thrown */
                break;
        }
    }

    protected void p_unbind(Name name, Continuation cont) throws
        NamingException {
        HeadTail res = p_resolveIntermediate(name, cont);
        switch (res.getStatus()) {
            case TERMINAL_NNS_COMPONENT:
                c_unbind_nns(res.getHead(), cont);
                break;

            case TERMINAL_COMPONENT:
                c_unbind(res.getHead(), cont);
                break;

            default:
                /* USE_CONTINUATION */
                /* cont already set or exception thrown */
                break;
        }
    }

    protected void p_destroySubcontext(Name name, Continuation cont) throws
        NamingException {
        HeadTail res = p_resolveIntermediate(name, cont);
        switch (res.getStatus()) {
            case TERMINAL_NNS_COMPONENT:
                c_destroySubcontext_nns(res.getHead(), cont);
                break;

            case TERMINAL_COMPONENT:
                c_destroySubcontext(res.getHead(), cont);
                break;

            default:
                /* USE_CONTINUATION */
                /* cont already set or exception thrown */
                break;
        }
    }

    protected Context p_createSubcontext(Name name, Continuation cont) throws
        NamingException {
            Context ret = null;
        HeadTail res = p_resolveIntermediate(name, cont);
        switch (res.getStatus()) {
            case TERMINAL_NNS_COMPONENT:
                ret = c_createSubcontext_nns(res.getHead(), cont);
                break;

            case TERMINAL_COMPONENT:
                ret = c_createSubcontext(res.getHead(), cont);
                break;

            default:
                /* USE_CONTINUATION */
                /* cont already set or exception thrown */
                break;
        }
        return ret;
    }

    protected void p_rename(Name oldName, Name newName, Continuation cont) throws
        NamingException {
        HeadTail res = p_resolveIntermediate(oldName, cont);
        switch (res.getStatus()) {
            case TERMINAL_NNS_COMPONENT:
                c_rename_nns(res.getHead(), newName, cont);
                break;

            case TERMINAL_COMPONENT:
                c_rename(res.getHead(), newName, cont);
                break;

            default:
                /* USE_CONTINUATION */
                /* cont already set or exception thrown */
                break;
        }
    }

    protected NameParser p_getNameParser(Name name, Continuation cont) throws
        NamingException {
        NameParser ret = null;
        HeadTail res = p_resolveIntermediate(name, cont);
        switch (res.getStatus()) {
            case TERMINAL_NNS_COMPONENT:
                ret = c_getNameParser_nns(res.getHead(), cont);
                break;

            case TERMINAL_COMPONENT:
                ret = c_getNameParser(res.getHead(), cont);
                break;

            default:
                /* USE_CONTINUATION */
                /* cont already set or exception thrown */
                break;
        }
        return ret;
    }

    protected Object p_lookupLink(Name name, Continuation cont)
        throws NamingException {
        Object ret = null;
        HeadTail res = p_resolveIntermediate(name, cont);
        switch (res.getStatus()) {
            case TERMINAL_NNS_COMPONENT:
                ret = c_lookupLink_nns(res.getHead(), cont);
                break;

            case TERMINAL_COMPONENT:
                ret = c_lookupLink(res.getHead(), cont);
                break;

            default:
                /* USE_CONTINUATION */
                /* cont already set or exception thrown */
                break;
        }
        return ret;
    }
}

/*
 *      How p_resolveIntermediate() should behave for various test cases

a.b/x   {a.b, x}
        c_resolveIntermediate_nns(a.b)
        continue(x)
        {x,}
        terminal(x)

a.b/    {a.b, ""}
        terminal_nns(a.b);

a.b//
        {a.b, ("", "")}
        c_lookup_nns(a.b)
        continue({""})
        {,""}
        terminal_nns({})

/x      {{}, {"", x}}
        c_lookup_nns({})
        continue(x)
        {x,}
        terminal(x)

//y     {{}, {"", "", y}}
        c_lookup_nns({})
        continue({"", y})
        {{}, {"", y}}
        c_lookup_nns({})
        continue(y)
        {y,}
        terminal(y)

a.b//y  {a.b, {"", y}}
        c_resolveIntermediate_nns(a.b)
        continue({"", y})
        {{}, {"",y}}
        c_lookup_nns({});
        continue(y)
        {y,}
        terminal(y);
 *
 */
