/**
   * Implements unbinding bound names in this NamingContext. If the name contains only one
   * component, the name is unbound in this NamingContext using Unbind(). Otherwise, the first
   * component of the name is resolved in this NamingContext and unbind passed to the resulting
   * NamingContext. This method is static for maximal reuse - even for extended naming context
   * implementations where the recursive semantics still apply.
   *
   * @param impl an implementation of NamingContextDataStore
   * @param n a sequence of NameComponents which is the name to be unbound.
   * @exception org.omg.CosNaming.NamingContextPackage.NotFound A name with multiple components was
   *     supplied, but the first component could not be resolved.
   * @exception org.omg.CosNaming.NamingContextPackage.CannotProceed Could not proceed in resolving
   *     the n-1 components of the supplied name.
   * @exception org.omg.CosNaming.NamingContextPackage.InvalidName The supplied name is invalid
   *     (i.e., has length less than 1).
   * @exception org.omg.CORBA.SystemException One of a fixed set of CORBA system exceptions.
   * @see resolve
   */
  public static void doUnbind(NamingContextDataStore impl, NameComponent[] n)
      throws org.omg.CosNaming.NamingContextPackage.NotFound,
          org.omg.CosNaming.NamingContextPackage.CannotProceed,
          org.omg.CosNaming.NamingContextPackage.InvalidName {
    // Name valid?
    if (n.length < 1) throw new InvalidName();

    // Unbind here?
    if (n.length == 1) {
      // The identifier must be set
      if ((n[0].id.length() == 0) && (n[0].kind.length() == 0)) {
        throw new InvalidName();
      }

      org.omg.CORBA.Object objRef = null;
      synchronized (impl) {
        // Yes: unbind in this context
        objRef = impl.Unbind(n[0]);
      }

      if (objRef == null)
        // It was not bound
        throw new NotFound(NotFoundReason.missing_node, n);
      // Done
      return;
    } else {
      // No: unbind in a different context

      // Resolve first  - must be resolveable
      NamingContext context = resolveFirstAsContext(impl, n);

      // Compute tail
      NameComponent[] tail = new NameComponent[n.length - 1];
      System.arraycopy(n, 1, tail, 0, n.length - 1);

      // Propagate unbind to this context
      context.unbind(tail);
    }
  }
  /**
   * Implements all four flavors of binding. It uses Resolve() to check if a binding already exists
   * (for bind and bind_context), and unbind() to ensure that a binding does not already exist. If
   * the length of the name is 1, then Bind() is called with the name and the object to bind.
   * Otherwise, the first component of the name is resolved in this NamingContext and the
   * appropriate form of bind passed to the resulting NamingContext. This method is static for
   * maximal reuse - even for extended naming context implementations where the recursive semantics
   * still apply.
   *
   * @param impl an implementation of NamingContextDataStore
   * @param n a sequence of NameComponents which is the name under which the object will be bound.
   * @param obj the object reference to be bound.
   * @param rebind Replace an existing binding or not.
   * @param bt Type of binding (as object or as context).
   * @exception org.omg.CosNaming.NamingContextPackage.NotFound A name with multiple components was
   *     supplied, but the first component could not be resolved.
   * @exception org.omg.CosNaming.NamingContextPackage.CannotProceed Could not * proceed in
   *     resolving the first component of the supplied name.
   * @exception org.omg.CosNaming.NamingContextPackage.InvalidName The supplied name is invalid
   *     (i.e., has length less than 1).
   * @exception org.omg.CosNaming.NamingContextPackage.AlreadyBound An object is already bound under
   *     the supplied name.
   * @exception org.omg.CORBA.SystemException One of a fixed set of CORBA system exceptions.
   * @see resolve
   * @see unbind
   * @see bind
   * @see bind_context
   * @see rebind
   * @see rebind_context
   */
  public static void doBind(
      NamingContextDataStore impl,
      NameComponent[] n,
      org.omg.CORBA.Object obj,
      boolean rebind,
      org.omg.CosNaming.BindingType bt)
      throws org.omg.CosNaming.NamingContextPackage.NotFound,
          org.omg.CosNaming.NamingContextPackage.CannotProceed,
          org.omg.CosNaming.NamingContextPackage.InvalidName,
          org.omg.CosNaming.NamingContextPackage.AlreadyBound {
    // Valid name?
    if (n.length < 1) throw new InvalidName();

    // At bottom level?
    if (n.length == 1) {
      // The identifier must be set
      if ((n[0].id.length() == 0) && (n[0].kind.length() == 0)) {
        throw new InvalidName();
      }

      // Ensure synchronization of backend
      synchronized (impl) {
        // Yes: bind object in this context under the name
        BindingTypeHolder bth = new BindingTypeHolder();
        if (rebind) {
          org.omg.CORBA.Object objRef = impl.Resolve(n[0], bth);
          if (objRef != null) {
            // Refer Naming Service Doc:00-11-01 section 2.2.3.4
            // If there is an object already bound with the name
            // and the binding type is not ncontext a NotFound
            // Exception with a reason of not a context has to be
            // raised.
            // Fix for bug Id: 4384628
            if (bth.value.value() == BindingType.nobject.value()) {
              if (bt.value() == BindingType.ncontext.value()) {
                throw new NotFound(NotFoundReason.not_context, n);
              }
            } else {
              // Previously a Context was bound and now trying to
              // bind Object. It is invalid.
              if (bt.value() == BindingType.nobject.value()) {
                throw new NotFound(NotFoundReason.not_object, n);
              }
            }
            impl.Unbind(n[0]);
          }

        } else {
          if (impl.Resolve(n[0], bth) != null)
            // "Resistence is futile." [Borg pickup line]
            throw new AlreadyBound();
        }

        // Now there are no other bindings under this name
        impl.Bind(n[0], obj, bt);
      }
    } else {
      // No: bind in a different context
      NamingContext context = resolveFirstAsContext(impl, n);

      // Compute tail
      NameComponent[] tail = new NameComponent[n.length - 1];
      System.arraycopy(n, 1, tail, 0, n.length - 1);

      // How should we propagate the bind
      switch (bt.value()) {
        case BindingType._nobject:
          {
            // Bind as object
            if (rebind) context.rebind(tail, obj);
            else context.bind(tail, obj);
          }
          break;
        case BindingType._ncontext:
          {
            // Narrow to a naming context using Java casts. It must
            // work.
            NamingContext objContext = (NamingContext) obj;
            // Bind as context
            if (rebind) context.rebind_context(tail, objContext);
            else context.bind_context(tail, objContext);
          }
          break;
        default:
          // This should not happen
          throw staticWrapper.namingCtxBadBindingtype();
      }
    }
  }