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