/**
  * 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);
 }
  /**
   * Remove leading or trailing empty components from name. Eg "/comp/env/" -> "comp/env"
   *
   * @param name the name to normalize
   * @return normalized name
   */
  public Name toCanonicalName(Name name) {
    Name canonicalName = name;

    if (name != null) {
      if (canonicalName.size() > 1) {
        if (canonicalName.get(0).equals("")) canonicalName = canonicalName.getSuffix(1);

        if (canonicalName.get(canonicalName.size() - 1).equals(""))
          canonicalName = canonicalName.getPrefix(canonicalName.size() - 1);
      }
    }

    return canonicalName;
  }
 /**
  * Unbinds a name from ctx, and removes parents if they are empty
  *
  * @param ctx the parent JNDI Context under which the name will be unbound
  * @param name The name to unbind
  * @throws javax.naming.NamingException for any error
  */
 public static void unbind(Context ctx, Name name) throws NamingException {
   ctx.unbind(name); // unbind the end node in the name
   int sz = name.size();
   // walk the tree backwards, stopping at the domain
   while (--sz > 0) {
     Name pname = name.getPrefix(sz);
     try {
       ctx.destroySubcontext(pname);
     } catch (NamingException e) {
       // log.trace("Unable to remove context " + pname, e);
       break;
     }
   }
 }
  /**
   * Lookup link bound to name
   *
   * @param name name of link binding
   * @return LinkRef or plain object bound at name
   * @exception NamingException if an error occurs
   */
  public Object lookupLink(Name name) throws NamingException {
    Name cname = toCanonicalName(name);

    if (cname == null) {
      NamingContext ctx = new NamingContext(_env, _name, _parent, _parser);
      ctx._bindings = _bindings;
      return ctx;
    }
    if (cname.size() == 0) throw new NamingException("Name is empty");

    if (cname.size() == 1) {
      Binding binding = getBinding(cname);
      if (binding == null) throw new NameNotFoundException();

      Object o = binding.getObject();

      // handle links by looking up the link
      if (o instanceof Reference) {
        // deference the object
        try {
          return NamingManager.getObjectInstance(o, cname.getPrefix(1), this, _env);
        } catch (NamingException e) {
          throw e;
        } catch (Exception e) {
          __log.warn("", e);
          throw new NamingException(e.getMessage());
        }
      } else {
        // object is either a LinkRef which we don't dereference
        // or a plain object in which case spec says we return it
        return o;
      }
    }

    // it is a multipart name, recurse to the first subcontext
    String firstComponent = cname.get(0);
    Object ctx = null;

    if (firstComponent.equals("")) ctx = this;
    else {
      Binding binding = getBinding(firstComponent);
      if (binding == null) throw new NameNotFoundException();

      ctx = binding.getObject();

      if (ctx instanceof Reference) {
        // deference the object
        try {
          ctx =
              NamingManager.getObjectInstance(
                  ctx, getNameParser("").parse(firstComponent), this, _env);
        } catch (NamingException e) {
          throw e;
        } catch (Exception e) {
          __log.warn("", e);
          throw new NamingException(e.getMessage());
        }
      }
    }

    if (!(ctx instanceof Context)) throw new NotContextException();

    return ((Context) ctx).lookup(cname.getSuffix(1));
  }