/**
   * This method obtains an IOR from a CORBA object reference. It will return null if obj is a local
   * object, a null object, or an object implemented by a different ORB. It will throw BAD_OPERATION
   * if obj is an unconnected RMI-IIOP object.
   *
   * @return IOR the IOR that represents this objref. This will never be null.
   * @exception BAD_OPERATION (from oi._get_delegate) if obj is a normal objref, but does not have a
   *     delegate set.
   * @exception BAD_PARAM if obj is a local object, or else was created by a foreign ORB.
   */
  public static IOR getIOR(org.omg.CORBA.Object obj) {
    if (obj == null) throw wrapper.nullObjectReference();

    IOR ior = null;
    if (StubAdapter.isStub(obj)) {
      org.omg.CORBA.portable.Delegate del = StubAdapter.getDelegate(obj);

      if (del instanceof CorbaClientDelegate) {
        CorbaClientDelegate cdel = (CorbaClientDelegate) del;
        ContactInfoList cil = cdel.getContactInfoList();

        if (cil instanceof CorbaContactInfoList) {
          CorbaContactInfoList ccil = (CorbaContactInfoList) cil;
          ior = ccil.getTargetIOR();
          if (ior == null) throw wrapper.nullIor();

          return ior;
        } else {
          // This is our code, but the ContactInfoList is not a
          // CorbaContactInfoList.  This should not happen, because
          // we are in the CORBA application of the DCSA framework.
          // This is a coding error, and thus an INTERNAL exception
          // should be thrown.
          // XXX needs minor code
          throw new INTERNAL();
        }
      }

      // obj is implemented by a foreign ORB, because the Delegate is not a
      // ClientDelegate.
      // XXX this case could be handled by marshalling and
      // unmarshalling.  However, object_to_string cannot be used
      // here, as it is implemented with getIOR.  Note that this
      // will require access to an ORB, so that we can create streams
      // as needed.  The ORB is available simply as io._orb().
      throw wrapper.objrefFromForeignOrb();
    } else throw wrapper.localObjectNotAllowed();
  }