| /* |
| * Copyright (c) 1999, 2011, 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 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<NameClassPair> c_list(Name name, |
| Continuation cont) throws NamingException; |
| protected abstract NamingEnumeration<Binding> 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 |
| * equivalent 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<NameClassPair> c_list_nns(Name name, |
| Continuation cont) throws NamingException { |
| c_processJunction_nns(name, cont); |
| return null; |
| } |
| |
| protected NamingEnumeration<Binding> 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<NameClassPair> p_list(Name name, Continuation cont) |
| throws NamingException { |
| NamingEnumeration<NameClassPair> 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<Binding> p_listBindings(Name name, Continuation cont) throws |
| NamingException { |
| NamingEnumeration<Binding> 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); |
| * |
| */ |