示例#1
0
  /**
   * Constructs a JNDI Binding object from the COS Naming binding object.
   *
   * @exception NameNotFound No objects under the name.
   * @exception CannotProceed Unable to obtain a continuation context
   * @exception InvalidName Name not understood.
   * @exception NamingException One of the above.
   */
  private javax.naming.Binding mapBinding(org.omg.CosNaming.Binding bndg) throws NamingException {
    java.lang.Object obj = _ctx.callResolve(bndg.binding_name);

    Name cname = CNNameParser.cosNameToName(bndg.binding_name);

    try {
      obj = NamingManager.getObjectInstance(obj, cname, _ctx, _env);
    } catch (NamingException e) {
      throw e;
    } catch (Exception e) {
      NamingException ne = new NamingException("problem generating object using object factory");
      ne.setRootCause(e);
      throw ne;
    }

    // Use cname.toString() instead of bindingName because the name
    // in the binding should be a composite name
    String cnameStr = cname.toString();
    javax.naming.Binding jbndg = new javax.naming.Binding(cnameStr, obj);

    NameComponent[] comps = _ctx.makeFullName(bndg.binding_name);
    String fullName = CNNameParser.cosNameToInsString(comps);
    jbndg.setNameInNamespace(fullName);
    return jbndg;
  }
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      String methodName = method.getName();
      if (methodName.equals("toString") == true) return "Client ENC(" + clientName + ")";

      if (methodName.equals("lookup") == false)
        throw new OperationNotSupportedException("Only lookup is supported, op=" + method);
      NameParser parser = lookupCtx.getNameParser("");
      Name name = null;
      if (args[0] instanceof String) name = parser.parse((String) args[0]);
      else name = (Name) args[0];

      // Check for special objects not in the env
      if (name.size() < 2
          || "java:comp".equals(name.get(0)) == false
          || "env".equals(name.get(1)) == false) return getSpecialObject(name);
      // Lookup the client application context from the server
      Context clientCtx = (Context) lookupCtx.lookup(clientName);

      // JBAS-3967: EJB3 Client container hack
      try {
        clientCtx = (Context) clientCtx.lookup("env");
      } catch (NamingException e) {
        // ignore
        log.trace("No env sub context found", e);
      }

      // Strip the comp/env prefix
      Name bindingName = name.getSuffix(2);
      Object binding = clientCtx.lookup(bindingName);

      return binding;
    }
  /** Add the objects passed to the constructor to the JNDI Context addresses specified */
  public void setup() {

    try {
      InitialContext ic = new InitialContext();
      for (Iterator i = this.objectsToCreate.keySet().iterator(); i.hasNext(); ) {
        String name = (String) i.next();
        try {
          Name fullName = new CompositeName(name);
          Context currentContext = ic;
          while (fullName.size() > 1) {
            // Make contexts that are not already present
            try {
              currentContext = currentContext.createSubcontext(fullName.get(0));
            } catch (NamingException err) {
              currentContext = (Context) currentContext.lookup(fullName.get(0));
            }
            fullName = fullName.getSuffix(1);
          }
          ic.bind(name, this.objectsToCreate.get(name));
          Logger.log(Logger.FULL_DEBUG, JNDI_RESOURCES, "ContainerJNDIManager.BoundResource", name);
        } catch (NamingException err) {
          Logger.log(
              Logger.ERROR, JNDI_RESOURCES, "ContainerJNDIManager.ErrorBindingResource", name, err);
        }
      }
      Logger.log(
          Logger.DEBUG,
          JNDI_RESOURCES,
          "ContainerJNDIManager.SetupComplete",
          "" + this.objectsToCreate.size());
    } catch (NamingException err) {
      Logger.log(
          Logger.ERROR, JNDI_RESOURCES, "ContainerJNDIManager.ErrorGettingInitialContext", err);
    }
  }
 @Override
 public void applicationStarted(ComponentContext context) {
   if (namingContext != null) {
     return;
   }
   namingContext = NuxeoContainer.getRootContext();
   // allocate datasource sub-contexts
   Name comp;
   try {
     comp = new CompositeName(DataSourceHelper.getDataSourceJNDIPrefix());
   } catch (NamingException e) {
     throw new RuntimeException(e);
   }
   Context ctx = namingContext;
   for (int i = 0; i < comp.size(); i++) {
     try {
       ctx = (Context) ctx.lookup(comp.get(i));
     } catch (NamingException e) {
       try {
         ctx = ctx.createSubcontext(comp.get(i));
       } catch (NamingException e1) {
         throw new RuntimeException(e1);
       }
     }
   }
   // bind datasources
   for (DataSourceDescriptor datasourceDesc : datasources.values()) {
     bindDataSource(datasourceDesc);
   }
   // bind links
   for (DataSourceLinkDescriptor linkDesc : links.values()) {
     bindDataSourceLink(linkDesc);
   }
 }
示例#5
0
  /** Lists the names for the context. */
  public NamingEnumeration list(Name name) throws NamingException {
    AbstractModel model = _model;

    if (name == null) {
      return new QNameClassEnumeration(create(model, _env), model.list());
    }

    for (int i = 0; i < name.size(); i++) {
      String first = name.get(i);

      Object value = model.lookup(first);

      if (value instanceof AbstractModel) {
        model = (AbstractModel) value;
        continue;
      }

      value = dereference(value, null, model);

      if (value instanceof Context) return ((Context) value).list(name.getSuffix(i + 1));
      else if (value != null)
        throw new NotContextException(
            L.l("{0}: expected intermediate context at `{1}'", getFullPath(name), value));
      else throw new NameNotFoundException(getFullPath(name));
    }

    return new QNameClassEnumeration(create(model, _env), model.list());
  }
示例#6
0
 /**
  * Rebind val to name in ctx, and make sure that all intermediate contexts exist
  *
  * @param ctx the parent JNDI Context under which value will be bound
  * @param name the name relative to ctx where value will be bound
  * @param value the value to bind.
  * @throws javax.naming.NamingException for any error
  */
 public static void rebind(final Context ctx, final Name name, final Object value)
     throws NamingException {
   final int size = name.size();
   final String atom = name.get(size - 1);
   final Context parentCtx = createSubcontext(ctx, name.getPrefix(size - 1));
   parentCtx.rebind(atom, value);
 }
示例#7
0
  /**
   * This postparses a name, after it has been returned from the jndi operation. It assumes that it
   * has got a jndi <i>CompositeName</i> that needs to be converted to a legal ldap dn (i.e. an ldap
   * <i>CompoundName</i>). If this is *not* the case, there will be trouble...
   *
   * @param name the post jndi operation name.
   * @return the re-formatted version used by the application, as a DN object.
   */
  public Name postParse(String name) {
    /* EMERGENCY HACK
     * (JNDI apparently does not handle terminating spaces correctly - it
     * retains the escape characters, but trims the actual space, resulting
     * in an illegal ldap dn)
     */
    if (name.charAt(name.length() - 1) == '\\') {
      name = NameUtility.checkEndSpaces(name);
    }

    try {
      Name cn = new CompositeName(name);
      if (cn.size() == 0) // if the name is empty ...
      return new DN(); // ... just return an empty DN

      return new DN(
          cn.get(
              cn.size()
                  - 1)); // get the last element of the composite name, which will be the ldap
                         // compound name, and init the DN with that.
    } catch (NamingException e) // should never happen :-) (ROTFL)
    {
      log.log(
          Level.WARNING,
          "unexpected error: bad name back from jndi ftn in CBOps.postParse("
              + name
              + ")?\n"
              + e.toString());
      e.printStackTrace();
      // System.exit(-1);
      return new DN(name); // bad server response?  return (possibly) corrupt name anyway...
    }
  }
示例#8
0
  public void destroySubcontext(Name name) throws NamingException {
    if (name.size() == 0) throw new NamingException(L.l("can't destroy root subcontext"));

    AbstractModel model = _model;

    int i = 0;
    for (; i + 1 < name.size(); i++) {
      String first = name.get(i);

      Object value = model.lookup(first);

      if (value instanceof AbstractModel) {
        model = (AbstractModel) value;
        continue;
      }

      value = dereference(value, null, model);

      if (value instanceof Context) {
        ((Context) value).destroySubcontext(name.getSuffix(i + 1));
        return;
      } else if (value != null)
        throw new NotContextException(
            L.l("{0}: expected intermediate context at `{1}'", getFullPath(name), value));
      else throw new NameNotFoundException(getFullPath(name));
    }

    String first = name.get(i);

    model.unbind(first);
  }
示例#9
0
  public void rebind(Name name, Object obj) throws NamingException {
    if (name.size() == 0) throw new NamingException(L.l("can't bind root"));

    AbstractModel model = _model;

    int i = 0;
    for (; i + 1 < name.size(); i++) {
      String first = name.get(i);

      Object value = model.lookup(first);

      if (value instanceof AbstractModel) {
        model = (AbstractModel) value;
        continue;
      }

      value = dereference(value, null, model);

      if (value instanceof Context) {
        ((Context) value).bind(name.getSuffix(i + 1), obj);
        return;
      } else if (value != null)
        throw new NotContextException(
            L.l("{0}: expected intermediate context at `{1}'", getFullPath(name), value));
      else throw new NameNotFoundException(getFullPath(name));
    }

    String first = name.get(i);

    if (obj == null) obj = NullValue.NULL;

    model.bind(first, getReference(model, obj));
  }
示例#10
0
  /**
   * Add a name to object binding to this Context.
   *
   * @param name a <code>Name</code> value
   * @param obj an <code>Object</code> value
   */
  public void addBinding(Name name, Object obj) throws NameAlreadyBoundException {
    String key = name.toString();
    Binding binding = new Binding(key, obj);

    Collection<Listener> list = findListeners();

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

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

    if (binding != null) {
      if (_bindings.containsKey(key)) {
        if (_supportDeepBinding) {
          // quietly return (no exception)
          // this is jndi spec breaking, but is added to support broken
          // jndi users like openejb.
          return;
        }
        throw new NameAlreadyBoundException(name.toString());
      }
      _bindings.put(key, binding);
    }
  }
示例#11
0
  @Test
  public void testgetParent() throws InvalidNameException {
    Name name = new LdapName("cn=test,ou=personnes,o=foo,c=bar");

    Name parent = LdapUtils.getDistinguishedNameParent(name);

    Assert.assertEquals(new LdapName("ou=personnes,o=foo,c=bar"), parent);

    Name c = LdapUtils.getDistinguishedNamePrefix(name, "c");

    Name o = LdapUtils.getDistinguishedNamePrefix(name, "o");

    Name ou = LdapUtils.getDistinguishedNamePrefix(name, "ou");

    Name cn = LdapUtils.getDistinguishedNamePrefix(name, "cn");

    Name x = LdapUtils.getDistinguishedNamePrefix(name, "x");

    Assert.assertEquals(new LdapName("c=bar"), c);

    Assert.assertEquals(new LdapName("o=foo,c=bar"), o);

    Assert.assertEquals(new LdapName("ou=personnes,o=foo,c=bar"), ou);

    Assert.assertEquals(name, cn);

    Assert.assertNull(x);

    Assert.assertEquals(
        new LdapName("ou=structures,o=foo,c=bar"), o.addAll(new LdapName("ou=structures")));
  }
 public List<Binding> listBindings(final Name name) throws NamingException {
   final ServiceName lookupName = buildServiceName(name);
   final ServiceName floor = boundServices.floor(lookupName);
   if (floor != null && floor.isParentOf(lookupName)) {
     // Parent might be a reference or a link
     Object obj = lookup(name.toString(), floor);
     if (obj != null) throw new RequireResolveException(convert(floor));
   }
   final List<ServiceName> children = listChildren(lookupName);
   final String[] lookupParts = lookupName.toArray();
   final Set<String> childContexts = new HashSet<String>();
   final List<Binding> results = new ArrayList<Binding>();
   for (ServiceName child : children) {
     final String[] childParts = child.toArray();
     if (childParts.length > lookupParts.length + 1) {
       childContexts.add(childParts[lookupParts.length]);
     } else {
       final Object binding = lookup(name.toString(), child);
       results.add(new Binding(childParts[childParts.length - 1], binding));
     }
   }
   for (String contextName : childContexts) {
     results.add(
         new Binding(
             contextName, new NamingContext(((Name) name.clone()).add(contextName), this, null)));
   }
   return results;
 }
示例#13
0
  private Object lookupImpl(Name name) throws NamingException {
    if (log.isLoggable(Level.FINEST)) log.finest(L.l("JNDI lookup `{0}'", name));

    if (name == null) return create(_model, _env);

    AbstractModel model = _model;

    for (int i = 0; i < name.size(); i++) {
      String first = name.get(i);

      Object value = model.lookup(first);

      if (value instanceof AbstractModel) {
        model = (AbstractModel) value;
        continue;
      }

      value = dereference(value, null, model);

      if (i + 1 == name.size()) {
        return value;
      } else if (value instanceof Context) {
        return ((Context) value).lookup(name.getSuffix(i + 1));
      } else if (value != null)
        throw new NotContextException(
            L.l("{0}: expected intermediate context at `{1}'", getFullPath(name), value));
      else throw new NameNotFoundException(getFullPath(name));
    }

    return create(getFullPath(name), model, _env);
  }
  /**
   * Bind val to name in ctx, and make sure that all intermediate contexts exist.
   *
   * @param ctx the root context
   * @param name the name as a string
   * @param val the object to be bound
   * @throws NamingException
   */
  public static void bind(Context ctx, String name, Object val) throws NamingException {
    try {
      log.trace("binding: " + name);
      ctx.rebind(name, val);
    } catch (Exception e) {
      Name n = ctx.getNameParser("").parse(name);
      while (n.size() > 1) {
        String ctxName = n.get(0);

        Context subctx = null;
        try {
          log.trace("lookup: " + ctxName);
          subctx = (Context) ctx.lookup(ctxName);
        } catch (NameNotFoundException nfe) {
        }

        if (subctx != null) {
          log.debug("Found subcontext: " + ctxName);
          ctx = subctx;
        } else {
          log.info("Creating subcontext: " + ctxName);
          ctx = ctx.createSubcontext(ctxName);
        }
        n = n.getSuffix(1);
      }
      log.trace("binding: " + n);
      ctx.rebind(n, val);
    }
    log.debug("Bound name: " + name);
  }
示例#15
0
  /** Looks up an object with the given parsed JNDI name, but don't dereference the final object. */
  public Object lookupLink(Name name) throws NamingException {
    if (name == null) return create(_model, _env);

    AbstractModel model = _model;

    for (int i = 0; i < name.size(); i++) {
      String first = name.get(i);

      Object value = model.lookup(first);

      if (value instanceof AbstractModel) {
        model = (AbstractModel) value;
        continue;
      }

      if (i + 1 == name.size()) {
        if (value == NullValue.NULL) return null;
        else if (value != null) return value;
        else throw new NameNotFoundException(getFullPath(name));
      }

      value = dereference(value, null, model);

      if (value instanceof Context) return ((Context) value).lookupLink(name.getSuffix(i + 1));
      else if (value != null)
        throw new NotContextException(
            L.l("{0}: expected intermediate context at `{1}'", getFullPath(name), value));
      else throw new NameNotFoundException(getFullPath(name));
    }

    return create(getFullPath(name), model, _env);
  }
  /**
   * Construct a DirContextAdapter given the supplied paramters. The <code>name</code> is normally a
   * JNDI <code>CompositeName</code>, which needs to be handled with particuclar care. Specifically
   * the escaping of a <code>CompositeName</code> destroys proper escaping of Distinguished Names.
   * Also, the name might contain referral information, in which case we need to separate the server
   * information from the actual Distinguished Name so that we can create a representing
   * DirContextAdapter.
   *
   * @param attrs the attributes
   * @param name the Name, typically a <code>CompositeName</code>, possibly including referral
   *     information.
   * @param nameInNamespace the Name in namespace.
   * @return a {@link DirContextAdapter} representing the specified information.
   */
  DirContextAdapter constructAdapterFromName(Attributes attrs, Name name, String nameInNamespace) {
    String nameString;
    String referralUrl = "";

    if (name instanceof CompositeName) {
      // Which it most certainly will be, and therein lies the
      // problem. CompositeName.toString() completely screws up the
      // formatting
      // in some cases, particularly when backslashes are involved.
      nameString = LdapUtils.convertCompositeNameToString((CompositeName) name);
    } else {
      LOG.warn(
          "Expecting a CompositeName as input to getObjectInstance but received a '"
              + name.getClass().toString()
              + "' - using toString and proceeding with undefined results");
      nameString = name.toString();
    }

    if (nameString.startsWith(LDAP_PROTOCOL_PREFIX)
        || nameString.startsWith(LDAPS_PROTOCOL_PREFIX)) {
      if (LOG.isDebugEnabled()) {
        LOG.debug(
            "Received name '"
                + nameString
                + "' contains protocol delimiter; indicating a referral."
                + "Stripping protocol and address info to enable construction of a proper LdapName");
      }
      try {
        URI url = new URI(nameString);
        String pathString = url.getPath();
        referralUrl = nameString.substring(0, nameString.length() - pathString.length());

        if (StringUtils.hasLength(pathString) && pathString.startsWith("/")) {
          // We don't want any slash in the beginning of the
          // Distinguished Name.
          pathString = pathString.substring(1);
        }

        nameString = pathString;
      } catch (URISyntaxException e) {
        throw new IllegalArgumentException(
            "Supplied name starts with protocol prefix indicating a referral,"
                + " but is not possible to parse to an URI",
            e);
      }
      if (LOG.isDebugEnabled()) {
        LOG.debug("Resulting name after removal of referral information: '" + nameString + "'");
      }
    }

    DirContextAdapter dirContextAdapter =
        new DirContextAdapter(
            attrs,
            LdapUtils.newLdapName(nameString),
            LdapUtils.newLdapName(nameInNamespace),
            referralUrl);
    dirContextAdapter.setUpdateMode(true);
    return dirContextAdapter;
  }
示例#17
0
  /**
   * Join two names together. These are treated as CompoundNames.
   *
   * @param name a <code>Name</code> value
   * @param prefix a <code>Name</code> value
   * @return a <code>Name</code> value
   * @exception NamingException if an error occurs
   */
  public Name composeName(Name name, Name prefix) throws NamingException {
    if (name == null) throw new NamingException("Name cannot be null");
    if (prefix == null) throw new NamingException("Prefix cannot be null");

    Name compoundName = (CompoundName) prefix.clone();
    compoundName.addAll(name);
    return compoundName;
  }
示例#18
0
  public NameParser getNameParser(Name name) throws NamingException {
    if (name.size() == 0) return new QNameParser(this);

    Object obj = lookupSingleObject(name.get(0));

    if (obj instanceof Context) return ((Context) obj).getNameParser(name.getSuffix(1));
    else return new QNameParser(this);
  }
示例#19
0
  /** Returns the full name for the context. */
  protected String getFullPath(Name name) {
    if (_name == null || _name.equals("")) return name.toString();
    else if (name == null || name.size() == 0) return _name;

    String sep = getSeparatorString();

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

    Name compoundName = _parser.parse(prefix);
    compoundName.add(name);
    return compoundName.toString();
  }
示例#21
0
  /** Resolves to nns associated with 'name' and set Continuation to the result. */
  protected void resolve_to_nns_and_continue(Name name, Continuation cont) throws NamingException {
    if (debug > 0) System.out.println("RESOLVE TO NNS AND CONTINUE" + name.toString());

    if (resolve_to_penultimate_context_nns(name, cont)) {
      Object nns = a_lookup_nns(name.toString(), cont);
      if (nns != null) cont.setContinue(nns, name, this);
    }
  }
示例#22
0
 /** {@inheritDoc} */
 public void rename(Name oldName, Name newName) throws NamingException {
   if (oldName.isEmpty() || newName.isEmpty()) {
     throw new InvalidNameException("empty name");
   } else {
     Object obj = lookup(oldName);
     bind(newName, obj);
     unbind(oldName);
   }
 }
    @Test
    public void shouldParsePowerApiScheme() throws Exception {
      final Name name = context.getNameParser(SUBCONTEXT_REF).parse(SUBCONTEXT_REF);

      assertFalse("Name must not be null", name.isEmpty());
      assertEquals(
          "First part of complex context name should be subcontext", "subcontext", name.get(0));
      assertEquals("Second part of complex context name should be object", "object", name.get(1));
    }
示例#24
0
 /** Entry tree lookup. */
 protected Entry treeLookup(Name name) {
   if (name.isEmpty() || entries == null) return entries;
   Entry currentEntry = entries;
   for (int i = 0; i < name.size(); i++) {
     if (name.get(i).length() == 0) continue;
     currentEntry = currentEntry.getChild(name.get(i));
     if (currentEntry == null) return null;
   }
   return currentEntry;
 }
 protected final String getAtom(String dn) {
   // need to strip off all but lowest component of dn
   // so that is relative to current context (currentDN)
   try {
     Name parsed = new LdapName(dn);
     return parsed.get(parsed.size() - 1);
   } catch (NamingException e) {
     return dn;
   }
 }
  /**
   * Destroys the named context and removes it from the namespace. Any attributes associated with
   * the name are also removed. Intermediate contexts are not destroyed.
   *
   * <p>This method is idempotent. It succeeds even if the terminal atomic name is not bound in the
   * target context, but throws NameNotFoundException if any of the intermediate contexts do not
   * exist.
   *
   * <p>In a federated naming system, a context from one naming system may be bound to a name in
   * another. One can subsequently look up and perform operations on the foreign context using a
   * composite name. However, an attempt destroy the context using this composite name will fail
   * with NotContextException, because the foreign context is not a "subcontext" of the context in
   * which it is bound. Instead, use unbind() to remove the binding of the foreign context.
   * Destroying the foreign context requires that the destroySubcontext() be performed on a context
   * from the foreign context's "native" naming system.
   *
   * @param name the name of the context to be destroyed; may not be empty
   * @exception NameNotFoundException if an intermediate context does not exist
   * @exception NotContextException if the name is bound but does not name a context, or does not
   *     name a context of the appropriate type
   */
  @Override
  public void destroySubcontext(Name name) throws NamingException {

    if (!checkWritable()) {
      return;
    }

    while ((!name.isEmpty()) && (name.get(0).length() == 0)) name = name.getSuffix(1);
    if (name.isEmpty()) throw new NamingException(sm.getString("namingContext.invalidName"));

    NamingEntry entry = bindings.get(name.get(0));

    if (entry == null) {
      throw new NameNotFoundException(
          sm.getString("namingContext.nameNotBound", name, name.get(0)));
    }

    if (name.size() > 1) {
      if (entry.type == NamingEntry.CONTEXT) {
        ((Context) entry.value).destroySubcontext(name.getSuffix(1));
      } else {
        throw new NamingException(sm.getString("namingContext.contextExpected"));
      }
    } else {
      if (entry.type == NamingEntry.CONTEXT) {
        ((Context) entry.value).close();
        bindings.remove(name.get(0));
      } else {
        throw new NotContextException(sm.getString("namingContext.contextExpected"));
      }
    }
  }
示例#27
0
  /**
   * Get the full name of this Context node by visiting it's ancestors back to root.
   *
   * <p>NOTE: if this Context has a URL namespace then the URL prefix will be missing
   *
   * @return the full name of this Context
   * @exception NamingException if an error occurs
   */
  public String getNameInNamespace() throws NamingException {
    Name name = _parser.parse("");

    NamingContext c = this;
    while (c != null) {
      String str = c.getName();
      if (str != null) name.add(0, str);
      c = (NamingContext) c.getParent();
    }
    return name.toString();
  }
 public NameParser getNameParser(Name name) throws NamingException {
   if (name.size() == 1) {
     return getNameParser(name.get(0));
   } else {
     Context ctx = getContinuationContext(name);
     try {
       return ctx.getNameParser(name.getSuffix(1));
     } finally {
       ctx.close();
     }
   }
 }
示例#29
0
 protected String getComponentName(Name name) throws NamingException {
   if (name instanceof CompositeName) {
     if (name.size() > 1) {
       throw new InvalidNameException(
           name.toString() + " has more components than namespace can handle");
     }
     return name.get(0);
   } else {
     // compound name
     return name.toString();
   }
 }
 public Object lookupLink(Name name) throws NamingException {
   if (name.size() == 1) {
     return lookupLink(name.get(0));
   } else {
     Context ctx = getContinuationContext(name);
     try {
       return ctx.lookupLink(name.getSuffix(1));
     } finally {
       ctx.close();
     }
   }
 }