/**
   * Create a naming context servant. Runs the super constructor.
   *
   * @param orb an ORB object.
   * @exception java.lang.Exception a Java exception.
   */
  public NamingContextImpl(ORB orb, POA poa) throws java.lang.Exception {
    super();
    this.orb = orb;
    wrapper = NamingSystemException.get(orb, CORBALogDomains.NAMING_UPDATE);

    insImpl = new InterOperableNamingImpl();
    this.nsPOA = poa;
    readLogger = orb.getLogger(CORBALogDomains.NAMING_READ);
    updateLogger = orb.getLogger(CORBALogDomains.NAMING_UPDATE);
    lifecycleLogger = orb.getLogger(CORBALogDomains.NAMING_LIFECYCLE);
  }
/**
 * Class NamingContextImpl implements the org.omg.CosNaming::NamingContext interface, but does not
 * implement the methods associated with maintaining the "table" of current bindings in a
 * NamingContext. Instead, this implementation assumes that the derived implementation implements
 * the NamingContextDataStore interface, which has the necessary methods. This allows multiple
 * NamingContext implementations that differ in storage of the bindings, as well as implementations
 * of interfaces derived from CosNaming::NamingContext that still reuses the implementation.
 *
 * <p>The operations bind(), rebind(), bind_context() and rebind_context() are all really
 * implemented by doBind(). resolve() is really implemented by doResolve(), unbind() by doUnbind().
 * list(), new_context() and destroy() uses the NamingContextDataStore interface directly. All the
 * doX() methods are public static. They synchronize on the NamingContextDataStore object.
 *
 * <p>An implementation a NamingContext must extend this class and implement the
 * NamingContextDataStore interface with the operations: Bind(), Resolve(), Unbind(), List(),
 * NewContext() and Destroy(). Calls to these methods are synchronized; these methods should
 * therefore not be synchronized.
 */
public abstract class NamingContextImpl extends NamingContextExtPOA
    implements NamingContextDataStore {

  protected POA nsPOA;
  private Logger readLogger, updateLogger, lifecycleLogger;
  private NamingSystemException wrapper;
  private static NamingSystemException staticWrapper =
      NamingSystemException.get(CORBALogDomains.NAMING_UPDATE);

  // The grammer for Parsing and Building Interoperable Stringified Names
  // are implemented in this class
  private InterOperableNamingImpl insImpl;
  /**
   * Create a naming context servant. Runs the super constructor.
   *
   * @param orb an ORB object.
   * @exception java.lang.Exception a Java exception.
   */
  public NamingContextImpl(ORB orb, POA poa) throws java.lang.Exception {
    super();
    this.orb = orb;
    wrapper = NamingSystemException.get(orb, CORBALogDomains.NAMING_UPDATE);

    insImpl = new InterOperableNamingImpl();
    this.nsPOA = poa;
    readLogger = orb.getLogger(CORBALogDomains.NAMING_READ);
    updateLogger = orb.getLogger(CORBALogDomains.NAMING_UPDATE);
    lifecycleLogger = orb.getLogger(CORBALogDomains.NAMING_LIFECYCLE);
  }

  public POA getNSPOA() {
    return nsPOA;
  }

  /**
   * Bind an object under a name in this NamingContext. If the name contains multiple (n)
   * components, n-1 will be resolved in this NamingContext and the object bound in resulting
   * NamingContext. An exception is thrown if a binding with the supplied name already exists. If
   * the object to be bound is a NamingContext it will not participate in a recursive resolve.
   *
   * @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.
   * @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.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 doBind
   */
  public void bind(NameComponent[] n, org.omg.CORBA.Object obj)
      throws org.omg.CosNaming.NamingContextPackage.NotFound,
          org.omg.CosNaming.NamingContextPackage.CannotProceed,
          org.omg.CosNaming.NamingContextPackage.InvalidName,
          org.omg.CosNaming.NamingContextPackage.AlreadyBound {
    if (obj == null) {
      updateLogger.warning(
          LogKeywords.NAMING_BIND + " unsuccessful because NULL Object cannot be Bound ");
      throw wrapper.objectIsNull();
    }
    // doBind implements all four flavors of binding
    NamingContextDataStore impl = (NamingContextDataStore) this;
    doBind(impl, n, obj, false, BindingType.nobject);
    if (updateLogger.isLoggable(Level.FINE)) {
      // isLoggable call to make sure that we save some precious
      // processor cycles, if there is no need to log.
      updateLogger.fine(
          LogKeywords.NAMING_BIND_SUCCESS + " Name = " + NamingUtils.getDirectoryStructuredName(n));
    }
  }

  /**
   * Bind a NamingContext under a name in this NamingContext. If the name contains multiple (n)
   * components, n-1 will be resolved in this NamingContext and the object bound in resulting
   * NamingContext. An exception is thrown if a binding with the supplied name already exists. The
   * NamingContext will participate in recursive resolving.
   *
   * @param n a sequence of NameComponents which is the name under which the object will be bound.
   * @param obj the NamingContect object reference to be bound.
   * @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.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 doBind
   */
  public void bind_context(NameComponent[] n, NamingContext nc)
      throws org.omg.CosNaming.NamingContextPackage.NotFound,
          org.omg.CosNaming.NamingContextPackage.CannotProceed,
          org.omg.CosNaming.NamingContextPackage.InvalidName,
          org.omg.CosNaming.NamingContextPackage.AlreadyBound {
    if (nc == null) {
      updateLogger.warning(LogKeywords.NAMING_BIND_FAILURE + " NULL Context cannot be Bound ");
      throw new BAD_PARAM("Naming Context should not be null ");
    }
    // doBind implements all four flavors of binding
    NamingContextDataStore impl = (NamingContextDataStore) this;
    doBind(impl, n, nc, false, BindingType.ncontext);
    if (updateLogger.isLoggable(Level.FINE)) {
      // isLoggable call to make sure that we save some precious
      // processor cycles, if there is no need to log.
      updateLogger.fine(
          LogKeywords.NAMING_BIND_SUCCESS + " Name = " + NamingUtils.getDirectoryStructuredName(n));
    }
  }

  /**
   * Bind an object under a name in this NamingContext. If the name contains multiple (n)
   * components, n-1 will be resolved in this NamingContext and the object bound in resulting
   * NamingContext. If a binding under the supplied name already exists it will be unbound first. If
   * the object to be bound is a NamingContext it will not participate in a recursive resolve.
   *
   * @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.
   * @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 doBind
   */
  public void rebind(NameComponent[] n, org.omg.CORBA.Object obj)
      throws org.omg.CosNaming.NamingContextPackage.NotFound,
          org.omg.CosNaming.NamingContextPackage.CannotProceed,
          org.omg.CosNaming.NamingContextPackage.InvalidName {
    if (obj == null) {
      updateLogger.warning(LogKeywords.NAMING_REBIND_FAILURE + " NULL Object cannot be Bound ");
      throw wrapper.objectIsNull();
    }
    try {
      // doBind implements all four flavors of binding
      NamingContextDataStore impl = (NamingContextDataStore) this;
      doBind(impl, n, obj, true, BindingType.nobject);
    } catch (org.omg.CosNaming.NamingContextPackage.AlreadyBound ex) {
      updateLogger.warning(
          LogKeywords.NAMING_REBIND_FAILURE
              + NamingUtils.getDirectoryStructuredName(n)
              + " is already bound to a Naming Context");
      // This should not happen
      throw wrapper.namingCtxRebindAlreadyBound(ex);
    }
    if (updateLogger.isLoggable(Level.FINE)) {
      // isLoggable call to make sure that we save some precious
      // processor cycles, if there is no need to log.
      updateLogger.fine(
          LogKeywords.NAMING_REBIND_SUCCESS
              + " Name = "
              + NamingUtils.getDirectoryStructuredName(n));
    }
  }

  /**
   * Bind a NamingContext under a name in this NamingContext. If the name contains multiple (n)
   * components, the first n-1 components will be resolved in this NamingContext and the object
   * bound in resulting NamingContext. If a binding under the supplied name already exists it will
   * be unbound first. The NamingContext will participate in recursive resolving.
   *
   * @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.
   * @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 doBind
   */
  public void rebind_context(NameComponent[] n, NamingContext nc)
      throws org.omg.CosNaming.NamingContextPackage.NotFound,
          org.omg.CosNaming.NamingContextPackage.CannotProceed,
          org.omg.CosNaming.NamingContextPackage.InvalidName {
    if (nc == null) {
      updateLogger.warning(LogKeywords.NAMING_REBIND_FAILURE + " NULL Context cannot be Bound ");
      throw wrapper.objectIsNull();
    }
    try {
      // doBind implements all four flavors of binding
      NamingContextDataStore impl = (NamingContextDataStore) this;
      doBind(impl, n, nc, true, BindingType.ncontext);
    } catch (org.omg.CosNaming.NamingContextPackage.AlreadyBound ex) {
      // This should not happen
      updateLogger.warning(
          LogKeywords.NAMING_REBIND_FAILURE
              + NamingUtils.getDirectoryStructuredName(n)
              + " is already bound to a CORBA Object");
      throw wrapper.namingCtxRebindctxAlreadyBound(ex);
    }
    if (updateLogger.isLoggable(Level.FINE)) {
      // isLoggable call to make sure that we save some precious
      // processor cycles, if there is no need to log.
      updateLogger.fine(
          LogKeywords.NAMING_REBIND_SUCCESS
              + " Name = "
              + NamingUtils.getDirectoryStructuredName(n));
    }
  }

  /**
   * Resolve a name in this NamingContext and return the object reference bound to the name. If the
   * name contains multiple (n) components, the first component will be resolved in this
   * NamingContext and the remaining components resolved in the resulting NamingContext, provided
   * that the NamingContext bound to the first component of the name was bound with bind_context().
   *
   * @param n a sequence of NameComponents which is the name to be resolved.
   * @return the object reference bound under the supplied name.
   * @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 doResolve
   */
  public org.omg.CORBA.Object resolve(NameComponent[] n)
      throws org.omg.CosNaming.NamingContextPackage.NotFound,
          org.omg.CosNaming.NamingContextPackage.CannotProceed,
          org.omg.CosNaming.NamingContextPackage.InvalidName {
    // doResolve actually resolves
    NamingContextDataStore impl = (NamingContextDataStore) this;
    org.omg.CORBA.Object obj = doResolve(impl, n);
    if (obj != null) {
      if (readLogger.isLoggable(Level.FINE)) {
        readLogger.fine(
            LogKeywords.NAMING_RESOLVE_SUCCESS
                + " Name: "
                + NamingUtils.getDirectoryStructuredName(n));
      }
    } else {
      readLogger.warning(
          LogKeywords.NAMING_RESOLVE_FAILURE
              + " Name: "
              + NamingUtils.getDirectoryStructuredName(n));
    }
    return obj;
  }

  /**
   * Remove a binding from this NamingContext. If the name contains multiple (n) components, the
   * first n-1 components will be resolved from this NamingContext and the final component unbound
   * in the resulting NamingContext.
   *
   * @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 doUnbind
   */
  public void unbind(NameComponent[] n)
      throws org.omg.CosNaming.NamingContextPackage.NotFound,
          org.omg.CosNaming.NamingContextPackage.CannotProceed,
          org.omg.CosNaming.NamingContextPackage.InvalidName {
    // doUnbind actually unbinds
    NamingContextDataStore impl = (NamingContextDataStore) this;
    doUnbind(impl, n);
    if (updateLogger.isLoggable(Level.FINE)) {
      // isLoggable call to make sure that we save some precious
      // processor cycles, if there is no need to log.
      updateLogger.fine(
          LogKeywords.NAMING_UNBIND_SUCCESS
              + " Name: "
              + NamingUtils.getDirectoryStructuredName(n));
    }
  }

  /**
   * List the contents of this NamingContest. A sequence of bindings is returned (a BindingList)
   * containing up to the number of requested bindings, and a BindingIterator object reference is
   * returned for iterating over the remaining bindings.
   *
   * @param how_many The number of requested bindings in the BindingList.
   * @param bl The BindingList as an out parameter.
   * @param bi The BindingIterator as an out parameter.
   * @exception org.omg.CORBA.SystemException One of a fixed set of CORBA system exceptions.
   * @see BindingListHolder
   * @see BindingIteratorImpl
   */
  public void list(int how_many, BindingListHolder bl, BindingIteratorHolder bi) {
    // List actually generates the list
    NamingContextDataStore impl = (NamingContextDataStore) this;
    synchronized (impl) {
      impl.List(how_many, bl, bi);
    }
    if (readLogger.isLoggable(Level.FINE) && (bl.value != null)) {
      // isLoggable call to make sure that we save some precious
      // processor cycles, if there is no need to log.
      readLogger.fine(
          LogKeywords.NAMING_LIST_SUCCESS
              + "list("
              + how_many
              + ") -> bindings["
              + bl.value.length
              + "] + iterator: "
              + bi.value);
    }
  }

  /**
   * Create a NamingContext object and return its object reference.
   *
   * @return an object reference for a new NamingContext object implemented by this Name Server.
   * @exception org.omg.CORBA.SystemException One of a fixed set of CORBA system exceptions.
   */
  public synchronized NamingContext new_context() {
    // Create actually creates a new naming context
    lifecycleLogger.fine("Creating New Naming Context ");
    NamingContextDataStore impl = (NamingContextDataStore) this;
    synchronized (impl) {
      NamingContext nctx = impl.NewContext();
      if (nctx != null) {
        lifecycleLogger.fine(LogKeywords.LIFECYCLE_CREATE_SUCCESS);
      } else {
        // If naming context is null, then that must be a serious
        // error.
        lifecycleLogger.severe(LogKeywords.LIFECYCLE_CREATE_FAILURE);
      }
      return nctx;
    }
  }

  /**
   * Create a new NamingContext, bind it in this Naming Context and return its object reference.
   * This is equivalent to using new_context() followed by bind_context() with the supplied name and
   * the object reference for the newly created NamingContext.
   *
   * @param n a sequence of NameComponents which is the name to be unbound.
   * @return an object reference for a new NamingContext object implemented by this Name Server,
   *     bound to the supplied name.
   * @exception org.omg.CosNaming.NamingContextPackage.AlreadyBound An object is already bound under
   *     the supplied name.
   * @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 new_context
   * @see bind_context
   */
  public NamingContext bind_new_context(NameComponent[] n)
      throws org.omg.CosNaming.NamingContextPackage.NotFound,
          org.omg.CosNaming.NamingContextPackage.AlreadyBound,
          org.omg.CosNaming.NamingContextPackage.CannotProceed,
          org.omg.CosNaming.NamingContextPackage.InvalidName {
    NamingContext nc = null;
    NamingContext rnc = null;
    try {
      if (debug) dprint("bind_new_context " + nameToString(n));
      // The obvious solution:
      nc = this.new_context();
      this.bind_context(n, nc);
      rnc = nc;
      nc = null;
    } finally {
      try {
        if (nc != null) nc.destroy();
      } catch (org.omg.CosNaming.NamingContextPackage.NotEmpty e) {
      }
    }
    if (updateLogger.isLoggable(Level.FINE)) {
      // isLoggable call to make sure that we save some precious
      // processor cycles, if there is no need to log.
      updateLogger.fine(
          LogKeywords.NAMING_BIND
              + "New Context Bound To "
              + NamingUtils.getDirectoryStructuredName(n));
    }
    return rnc;
  }

  /**
   * Destroy this NamingContext object. If this NamingContext contains no bindings, the
   * NamingContext is deleted.
   *
   * @exception org.omg.CosNaming.NamingContextPackage.NotEmpty This NamingContext is not empty
   *     (i.e., contains bindings).
   * @exception org.omg.CORBA.SystemException One of a fixed set of CORBA system exceptions.
   */
  public void destroy() throws org.omg.CosNaming.NamingContextPackage.NotEmpty {
    lifecycleLogger.fine("Destroying Naming Context ");
    NamingContextDataStore impl = (NamingContextDataStore) this;
    synchronized (impl) {
      if (impl.IsEmpty() == true) {
        // The context is empty so it can be destroyed
        impl.Destroy();
        lifecycleLogger.fine(LogKeywords.LIFECYCLE_DESTROY_SUCCESS);
      } else {
        // This context is not empty!
        // Not a fatal error, warning should do.
        lifecycleLogger.warning(
            LogKeywords.LIFECYCLE_DESTROY_FAILURE
                + " NamingContext children are not destroyed still..");
        throw new NotEmpty();
      }
    }
  }

  /**
   * 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();
      }
    }
  }

  /**
   * Implements resolving names in this NamingContext. The first component of the supplied name is
   * resolved in this NamingContext by calling Resolve(). If there are no more components in the
   * name, the resulting object reference is returned. Otherwise, the resulting object reference
   * must have been bound as a context and be narrowable to a NamingContext. If this is the case,
   * the remaining components of the name is resolved in 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 resolved.
   * @return the object reference bound under the supplied name.
   * @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.CORBA.SystemException One of a fixed set of CORBA system exceptions.
   * @see resolve
   */
  public static org.omg.CORBA.Object doResolve(NamingContextDataStore impl, NameComponent[] n)
      throws org.omg.CosNaming.NamingContextPackage.NotFound,
          org.omg.CosNaming.NamingContextPackage.CannotProceed,
          org.omg.CosNaming.NamingContextPackage.InvalidName {
    org.omg.CORBA.Object obj = null;
    BindingTypeHolder bth = new BindingTypeHolder();

    // Length must be greater than 0
    if (n.length < 1) throw new InvalidName();

    // The identifier must be set
    if (n.length == 1) {
      synchronized (impl) {
        // Resolve first level in this context
        obj = impl.Resolve(n[0], bth);
      }
      if (obj == null) {
        // Object was not found
        throw new NotFound(NotFoundReason.missing_node, n);
      }
      return obj;
    } else {
      // n.length > 1
      if ((n[1].id.length() == 0) && (n[1].kind.length() == 0)) {
        throw new InvalidName();
      }

      NamingContext context = resolveFirstAsContext(impl, n);

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

      // Resolve rest of name in context
      try {
        // First try to resolve using the local call, this should work
        // most of the time unless there are federated naming contexts.
        Servant servant = impl.getNSPOA().reference_to_servant(context);
        return doResolve(((NamingContextDataStore) servant), tail);
      } catch (Exception e) {
        return context.resolve(tail);
      }
    }
  }

  /**
   * 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 resolving a NameComponent in this context and narrowing it to
   * CosNaming::NamingContext. It will throw appropriate exceptions if not found or not narrowable.
   *
   * @param impl an implementation of NamingContextDataStore
   * @param n a NameComponents which is the name to be found.
   * @exception org.omg.CosNaming.NamingContextPackage.NotFound 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.CORBA.SystemException One of a fixed set of CORBA system exceptions.
   * @see resolve
   */
  protected static NamingContext resolveFirstAsContext(
      NamingContextDataStore impl, NameComponent[] n)
      throws org.omg.CosNaming.NamingContextPackage.NotFound {
    org.omg.CORBA.Object topRef = null;
    BindingTypeHolder bth = new BindingTypeHolder();
    NamingContext context = null;

    synchronized (impl) {
      // Resolve first  - must be resolveable
      topRef = impl.Resolve(n[0], bth);
      if (topRef == null) {
        // It was not bound
        throw new NotFound(NotFoundReason.missing_node, n);
      }
    }

    // Was it bound as a context?
    if (bth.value != BindingType.ncontext) {
      // It was not a context
      throw new NotFound(NotFoundReason.not_context, n);
    }

    // Narrow to a naming context
    try {
      context = NamingContextHelper.narrow(topRef);
    } catch (org.omg.CORBA.BAD_PARAM ex) {
      // It was not a context
      throw new NotFound(NotFoundReason.not_context, n);
    }

    // Hmm. must be ok
    return context;
  }

  /**
   * This operation creates a stringified name from the array of Name components.
   *
   * @param n Name of the object
   *     <p>
   * @exception org.omg.CosNaming.NamingContextExtPackage.InvalidName Indicates the name does not
   *     identify a binding.
   *     <p>
   */
  public String to_string(org.omg.CosNaming.NameComponent[] n)
      throws org.omg.CosNaming.NamingContextPackage.InvalidName {
    // Name valid?
    if ((n == null) || (n.length == 0)) {
      throw new InvalidName();
    }
    NamingContextDataStore impl = (NamingContextDataStore) this;

    String theStringifiedName = insImpl.convertToString(n);

    if (theStringifiedName == null) {
      throw new InvalidName();
    }

    return theStringifiedName;
  }

  /**
   * This operation converts a Stringified Name into an equivalent array of Name Components.
   *
   * @param sn Stringified Name of the object
   *     <p>
   * @exception org.omg.CosNaming.NamingContextExtPackage.InvalidName Indicates the name does not
   *     identify a binding.
   *     <p>
   */
  public org.omg.CosNaming.NameComponent[] to_name(String sn)
      throws org.omg.CosNaming.NamingContextPackage.InvalidName {
    // Name valid?
    if ((sn == null) || (sn.length() == 0)) {
      throw new InvalidName();
    }
    NamingContextDataStore impl = (NamingContextDataStore) this;
    org.omg.CosNaming.NameComponent[] theNameComponents = insImpl.convertToNameComponent(sn);
    if ((theNameComponents == null) || (theNameComponents.length == 0)) {
      throw new InvalidName();
    }
    for (int i = 0; i < theNameComponents.length; i++) {
      // If there is a name component whose id and kind null or
      // zero length string, then an invalid name exception needs to be
      // raised.
      if (((theNameComponents[i].id == null) || (theNameComponents[i].id.length() == 0))
          && ((theNameComponents[i].kind == null) || (theNameComponents[i].kind.length() == 0))) {
        throw new InvalidName();
      }
    }
    return theNameComponents;
  }

  /**
   * This operation creates a URL based "iiopname://" format name from the Stringified Name of the
   * object.
   *
   * @param addr internet based address of the host machine where Name Service is running
   *     <p>
   * @param sn Stringified Name of the object
   *     <p>
   * @exception org.omg.CosNaming.NamingContextExtPackage.InvalidName Indicates the name does not
   *     identify a binding.
   *     <p>
   * @exception org.omg.CosNaming.NamingContextPackage.InvalidAddress Indicates the internet based
   *     address of the host machine is incorrect
   *     <p>
   */
  public String to_url(String addr, String sn)
      throws org.omg.CosNaming.NamingContextExtPackage.InvalidAddress,
          org.omg.CosNaming.NamingContextPackage.InvalidName {
    // Name valid?
    if ((sn == null) || (sn.length() == 0)) {
      throw new InvalidName();
    }
    if (addr == null) {
      throw new org.omg.CosNaming.NamingContextExtPackage.InvalidAddress();
    }
    NamingContextDataStore impl = (NamingContextDataStore) this;
    String urlBasedAddress = null;
    urlBasedAddress = insImpl.createURLBasedAddress(addr, sn);
    // Extra check to see that corba name url created is valid as per
    // INS spec grammer.
    try {
      INSURLHandler.getINSURLHandler().parseURL(urlBasedAddress);
    } catch (BAD_PARAM e) {
      throw new org.omg.CosNaming.NamingContextExtPackage.InvalidAddress();
    }
    return urlBasedAddress;
  }

  /**
   * This operation resolves the Stringified name into the object reference.
   *
   * @param sn Stringified Name of the object
   *     <p>
   * @exception org.omg.CosNaming.NamingContextPackage.NotFound Indicates there is no object
   *     reference for the given name.
   *     <p>
   * @exception org.omg.CosNaming.NamingContextPackage.CannotProceed Indicates that the given
   *     compound name is incorrect
   *     <p>
   * @exception org.omg.CosNaming.NamingContextExtPackage.InvalidName Indicates the name does not
   *     identify a binding.
   *     <p>
   * @exception org.omg.CosNaming.NamingContextPackage.AlreadyBound Indicates the name is already
   *     bound.
   *     <p>
   */
  public org.omg.CORBA.Object resolve_str(String sn)
      throws org.omg.CosNaming.NamingContextPackage.NotFound,
          org.omg.CosNaming.NamingContextPackage.CannotProceed,
          org.omg.CosNaming.NamingContextPackage.InvalidName {
    org.omg.CORBA.Object theObject = null;
    // Name valid?
    if ((sn == null) || (sn.length() == 0)) {
      throw new InvalidName();
    }
    NamingContextDataStore impl = (NamingContextDataStore) this;
    org.omg.CosNaming.NameComponent[] theNameComponents = insImpl.convertToNameComponent(sn);

    if ((theNameComponents == null) || (theNameComponents.length == 0)) {
      throw new InvalidName();
    }
    theObject = resolve(theNameComponents);
    return theObject;
  }

  protected transient ORB orb;

  public static String nameToString(NameComponent[] name) {
    StringBuffer s = new StringBuffer("{");
    if (name != null || name.length > 0) {
      for (int i = 0; i < name.length; i++) {
        if (i > 0) s.append(",");
        s.append("[").append(name[i].id).append(",").append(name[i].kind).append("]");
      }
    }
    s.append("}");
    return s.toString();
  }

  // Debugging aids.
  public static final boolean debug = false;

  private static void dprint(String msg) {
    NamingUtils.dprint(
        "NamingContextImpl("
            + Thread.currentThread().getName()
            + " at "
            + System.currentTimeMillis()
            + " ems): "
            + msg);
  }
}