// Open a single file, list the file attributes, and close the file.
  // Returns null if the file doesn't exist or is a directory.
  private IFSListAttrsRep listObjAttrs(int attrsType, int flags1, int flags2)
      throws IOException, AS400SecurityException {
    // Assume connect() has already been done.

    IFSListAttrsRep reply = null;
    int fileHandle = UNINITIALIZED;

    // Design note: In order to get an OA* structure back in the "List File Attributes" reply, we
    // must specify the file by handle rather than by name.

    boolean usedGlobalHandle = false; // @KKBA
    try {
      // Open the file, and obtain a file handle.
      if (fileHandle_ != UNINITIALIZED) // @KKBA
      { // @KKBA
        fileHandle = fileHandle_; // @KKBA
        usedGlobalHandle = true; // @KKBA
      } // @KKBA
      else {
        fileHandle = createFileHandle(); // @KKBC
        if (fileHandle == UNINITIALIZED) {
          if (Trace.traceOn_)
            Trace.log(
                Trace.ERROR,
                "Unable to create handle to file " + path_ + ". IFSReturnCodeRep return code",
                errorRC_);
          return null;
        }
      }

      // Send a 'list attributes' request, specifying the file handle we just created,
      // and indicating that we want an OA2 structure in the reply.

      IFSListAttrsReq req1 = new IFSListAttrsReq(fileHandle, attrsType, flags1, flags2);
      req1.setPatternMatching(patternMatching_);

      Vector replys = listAttributes(req1);

      // Verify that we got exactly one reply.
      if (replys == null) {
        if (Trace.traceOn_)
          Trace.log(Trace.WARNING, "Received null from listAttributes(fileHandle).");
      } else if (replys.size() == 0) {
        if (Trace.traceOn_)
          Trace.log(Trace.WARNING, "Received no replies from listAttributes(fileHandle).");
      } else if (replys.size() > 1) {
        if (Trace.traceOn_)
          Trace.log(
              Trace.WARNING,
              "Received multiple replies from listAttributes(fileHandle) (" + replys.size() + ")");
      } else {
        reply = (IFSListAttrsRep) replys.elementAt(0);
      }
    } finally {
      if (!usedGlobalHandle && fileHandle != UNINITIALIZED) // @KKBA
      close(fileHandle);
    }

    return reply;
  }
  // Submit the specified request, and fetch list attributes reply(s).
  // The returned Vector contains IFSListAttrsRep objects.
  Vector listAttributes(IFSListAttrsReq req) throws IOException, AS400SecurityException {
    // Assume connect() has already been done.

    errorRC_ = 0;
    Vector replys = new Vector(256);
    ClientAccessDataStream ds = null;
    try {
      ds = (ClientAccessDataStream) server_.sendAndReceive(req);
    } catch (ConnectionDroppedException e) {
      Trace.log(Trace.ERROR, "Byte stream server connection lost.");
      connectionDropped(e);
    } catch (InterruptedException e) {
      Trace.log(Trace.ERROR, "Interrupted");
      throw new InterruptedIOException(e.getMessage());
    }

    // @A1A
    int rc = -1; // @A1A

    boolean done = false;
    do {
      if (ds instanceof IFSListAttrsRep) {
        replys.addElement(ds);
      } else if (ds instanceof IFSReturnCodeRep) {
        // If the return code is NO_MORE_FILES then all files
        // that match the specification have been returned.
        rc = ((IFSReturnCodeRep) ds).getReturnCode();

        if (rc != IFSReturnCodeRep.SUCCESS
            && // @D4A
            rc != IFSReturnCodeRep.NO_MORE_FILES
            && rc != IFSReturnCodeRep.FILE_NOT_FOUND
            && rc != IFSReturnCodeRep.PATH_NOT_FOUND) {
          throwSecurityExceptionIfAccessDenied(path_, rc); // check for "access denied"
          Trace.log(
              Trace.ERROR,
              "Error getting file attributes for file "
                  + path_
                  + ": "
                  + "IFSReturnCodeRep return code",
              descriptionForReturnCode(rc));
          throw new ExtendedIOException(path_, rc);
        }

      } else {
        // Unknown data stream.
        Trace.log(Trace.ERROR, "Unknown reply data stream", ds.data_); // @A9C
        throw new InternalErrorException(
            Integer.toHexString(ds.getReqRepID()), InternalErrorException.DATA_STREAM_UNKNOWN);
      }

      // Fetch the next reply if not already done.
      done = ((IFSDataStream) ds).isEndOfChain();
      if (!done) {
        try {
          ds = (ClientAccessDataStream) server_.receive(req.getCorrelation());
        } catch (ConnectionDroppedException e) {
          Trace.log(Trace.ERROR, "Byte stream server connection lost.");
          connectionDropped(e);
        } catch (InterruptedException e) {
          Trace.log(Trace.ERROR, "Interrupted");
          throw new InterruptedIOException(e.getMessage());
        }
      }
    } while (!done);

    // @A1A
    if (rc == IFSReturnCodeRep.PATH_NOT_FOUND) { // @A1A
      // If the directory or file does not exist, then return NULL.
      errorRC_ = rc;
      replys = null; // @A1A
    } // @A1A
    else { // @A1A
      // Set the vector capacity to the current size.
      replys.trimToSize();
    } // @A1A

    return replys;
  }