All Downloads are FREE. Search and download functionalities are using the official Maven repository.

src.com.ibm.as400.access.IFSFileDescriptorImplRemote Maven / Gradle / Ivy

There is a newer version: 20.0.7
Show newest version
///////////////////////////////////////////////////////////////////////////////
//                                                                             
// JTOpen (IBM Toolbox for Java - OSS version)                              
//                                                                             
// Filename: IFSFileDescriptorImplRemote.java
//                                                                             
// The source code contained herein is licensed under the IBM Public License   
// Version 1.0, which has been approved by the Open Source Initiative.         
// Copyright (C) 1997-2000 International Business Machines Corporation and     
// others. All rights reserved.                                                
//                                                                             
///////////////////////////////////////////////////////////////////////////////
// @A3 - 10/18/2007 - Update finalize0() method to not send TWO close requests
//                    to the server.  When garbage collection finds a descriptor
//                    that has not been closed, it calls the finalize method on 
//                    one of the various IFSFilexxx classes which calls the 
//                    finalize0() method of this class.
//                    This class was sending TWO close requests to the server 
//                    for the same fileHandle_.  Normally, the second close would
//                    silently fail.  However, in some cases another thread might
//                    issue an open request for another file BETWEEN the two close
//                    requests sent by the garbage collection thread.  This 
//                    results in the newly opened file being incorrectly closed.
//                    Fix to finalize0() is to issue ONE close request to the 
//                    File server.
///////////////////////////////////////////////////////////////////////////////

package com.ibm.as400.access;

import java.io.IOException;
import java.io.InterruptedIOException;
import java.util.Vector;


/**
 Provides a full remote implementation for the IFSFileDescriptor class.
 **/
class IFSFileDescriptorImplRemote
implements IFSFileDescriptorImpl
{
  private static final int UNINITIALIZED = -1;  // @B8a
  private static final int MAX_BYTES_PER_READ = 16000000;  // limit of file server

  // Note: We allow direct access to some of these fields, for performance.  @B2C
          ConverterImplRemote converter_;
  private int         fileHandle_ = UNINITIALIZED;  // @B8c
          int         preferredServerCCSID_;
  private int         fileDataCCSID_ = UNINITIALIZED;
  private int         fileAsp_ = UNINITIALIZED;//@V4A
  private int         fileSystemType_ = UNINITIALIZED;//@V4A
          int         serverDatastreamLevel_; // @B3A
          int         requestedDatastreamLevel_; // @B6a
  private long        fileOffset_;
          boolean     isOpen_;
          boolean     isOpenAllowed_ = true;
  private Object      parent_;  // The object that instantiated this IFSDescriptor.
          String      path_ = "";
          byte[]      pathnameBytes_;
  transient Object    serverLock_ = new Object(); 
          AS400Server server_;  // Note: AS400Server is not serializable.
  private int         shareOption_;
          AS400ImplRemote system_;

  private Object      fileOffsetLock_ = new Object();
                         // Semaphore for synchronizing access to fileOffset_.

  private int         maxDataBlockSize_ = 1024; // @B2A
       // Used by IFSFileOutputStreamImplRemote, IFSRandomAccessFileImplRemote.

  private boolean     determinedSystemVRM_ = false;  // @B3A @B4C
  private int         systemVRM_;                    // @B3A @B4C
  transient int errorRC_;  // error return code from most recent request
          int         patternMatching_ = IFSFile.PATTERN_DEFAULT;  // pattern-matching semantics
  
  // Used for debugging only.  This should always be false for production.
  // When this is false, all debug code will theoretically compile out.
  private static final boolean DEBUG = false;  // @B3A
  
  //@AC7 Start
  String fileOwnerName_ = null;
  boolean isDirectory_ = false;
  //@AC7 End

  // Static initialization code.
  static
  {
    // Add all byte stream reply data streams of interest to the
    // AS400 server's reply data stream hash table.
    AS400Server.addReplyStream(new IFSCloseRep(), AS400.FILE);
    AS400Server.addReplyStream(new IFSExchangeAttrRep(), AS400.FILE);
    AS400Server.addReplyStream(new IFSLockBytesRep(), AS400.FILE);
    AS400Server.addReplyStream(new IFSReturnCodeRep(), AS400.FILE);
    AS400Server.addReplyStream(new IFSWriteRep(), AS400.FILE);
    AS400Server.addReplyStream(new IFSReadRep(), AS400.FILE);
  }


  // Cast an IFSFileDescriptorImpl object into an IFSFileDescriptorImplRemote.
  // Used by various IFS*ImplRemote classes.
  static IFSFileDescriptorImplRemote castImplToImplRemote(IFSFileDescriptorImpl fd)
  {
    try
    {
      return (IFSFileDescriptorImplRemote)fd;
    }
    catch (ClassCastException e)
    {
      Trace.log(Trace.ERROR, "Argument is not an instance of IFSFileDescriptorImplRemote", e);
      throw new
        InternalErrorException(InternalErrorException.UNEXPECTED_EXCEPTION);
    }
  }

  // @B8m  - Moved this method here from IFSFileImplRemote.
  // Determine if the directory entry can be accessed in the specified
  // manner.
  // Returns the returnCode that was set (as a side effect) by createFileHandle().
  int checkAccess(int access, int openOption)   // @D1C @B8c
    throws IOException, AS400SecurityException
  {
    int fileHandle = UNINITIALIZED;
    try {
      fileHandle = createFileHandle(access, openOption);
    }
    finally {
      if (fileHandle != UNINITIALIZED) close(fileHandle);  // we don't need this handle anymore
    }
    return errorRC_;
  }


  public void close()
  {
    try {
      close0();
    }
    catch (IOException e) {
      Trace.log(Trace.ERROR, "Error while closing file " + path_, e);
    }
  }


  public void close0() throws IOException
  {
    isOpen_ = false;
    close(fileHandle_);
    fileHandle_ = UNINITIALIZED;
  }

  void close(int fileHandle) throws IOException
  {
    if (fileHandle == UNINITIALIZED) return;  // @B8c

    // Close the file.  Send a close request to the server.
    ClientAccessDataStream ds = null;
    IFSCloseReq req = new IFSCloseReq(fileHandle);
    try
    {
      ds = (ClientAccessDataStream) server_.sendAndReceive(req);
    }
    catch(ConnectionDroppedException e)
    {
      Trace.log(Trace.ERROR, "Byte stream connection lost during close", e);
      connectionDropped(e);
    }
    catch(InterruptedException e)
    {
      Trace.log(Trace.ERROR, "Interrupted", e);
      InterruptedIOException throwException = new InterruptedIOException(e.getMessage());
      try {
        throwException.initCause(e); 
      } catch (Throwable t) {} 
      throw throwException;
    }

    // Validate the reply.
    if (ds instanceof IFSCloseRep)
    {
      int rc = ((IFSCloseRep) ds).getReturnCode();
      if (rc != 0)
      {
        Trace.log(Trace.ERROR, "IFSCloseRep return code", rc);
        throw new ExtendedIOException(path_, rc);
      }
    }
    else if (ds instanceof IFSReturnCodeRep)
    {
      int rc = ((IFSReturnCodeRep) ds).getReturnCode();
      if (rc != IFSReturnCodeRep.SUCCESS)
      {
        Trace.log(Trace.ERROR, "IFSReturnCodeRep return code", descriptionForReturnCode(rc));
        throw new ExtendedIOException(path_, rc);
      }
    }
    else
    {
      Trace.log(Trace.ERROR, "Unknown reply data stream", ds.data_);
      throw new
        InternalErrorException(Integer.toHexString(ds.getReqRepID()),
                               InternalErrorException.DATA_STREAM_UNKNOWN);
    }
  }


  /**
   Establishes communications with the server.

   @exception AS400SecurityException If a security or authority error occurs.
   @exception IOException If an error occurs while communicating with the server.
   **/
  void connect()  // @B2A - code relocated from IFSFileOutputStreamImplRemote,etc.
    throws IOException, AS400SecurityException
  {
    // Connect to the byte stream server if not already connected.
    if (server_ == null)
    {
      // Ensure that the system has been set.
      if (system_ == null)
      {
        throw new ExtendedIllegalStateException("system",
                                 ExtendedIllegalStateException.PROPERTY_NOT_SET);
      }

      try {
        server_ = system_.getConnection(AS400.FILE, false /*forceNewConnection*/, false /*skip signon server */ );
      }
      catch(AS400SecurityException e)
      {
        Trace.log(Trace.ERROR, "Access to byte stream server on '" +
                  system_.getSystemName() + "' denied.", e);
        throw e;
      }

      // Exchange attributes with the server.
      exchangeServerAttributes();
    }
  }

  /**
   Disconnects from the byte stream server.
   @exception ConnectionDroppedException If the connection is dropped unexpectedly.
   **/
  void connectionDropped(ConnectionDroppedException e) // @B2A - code relocated from IFSFileOutputStreamImplRemote,etc.
    throws ConnectionDroppedException
  {
    if (server_ != null)
    {
      system_.disconnectServer(server_);
      server_ = null;
      try { close(); } catch (Exception exc) {}  // Note: Not relevant for IFSFileImplRemote.
    }
    Trace.log(Trace.ERROR, "Byte stream connection lost.");
    throw e;
  }

  /**
   * Copies a file or directory to another file or directory.
  **/
  boolean copyTo(String destinationPath, boolean replace)
    throws AS400SecurityException, IOException
  {
    ClientAccessDataStream ds = null;
    IFSCopyReq req = new IFSCopyReq(path_, destinationPath, replace);
    try
    {
      ds = (ClientAccessDataStream) server_.sendAndReceive(req);
    }
    catch(ConnectionDroppedException e)
    {
      Trace.log(Trace.ERROR, "Byte stream connection lost during copy", e);
      connectionDropped(e);
    }
    catch(InterruptedException e)
    {
      Trace.log(Trace.ERROR, "Interrupted", e);
      InterruptedIOException throwException = new InterruptedIOException(e.getMessage());
      try {
        throwException.initCause(e); 
      } catch (Throwable t) {} 
      throw throwException;
    }
    if (ds instanceof IFSReturnCodeRep)
    {
      int rc = ((IFSReturnCodeRep) ds).getReturnCode();
      if (rc != IFSReturnCodeRep.SUCCESS)
      {
        String path = (rc == IFSReturnCodeRep.DUPLICATE_DIR_ENTRY_NAME ? destinationPath : path_);
        throwSecurityExceptionIfAccessDenied(path,rc); // check for "access denied"
        Trace.log(Trace.ERROR, "IFSReturnCodeRep return code", descriptionForReturnCode(rc));
        throw new ExtendedIOException(path, rc);
      }
      return true;
    }
    else
    {
      Trace.log(Trace.ERROR, "Unknown reply data stream", ds.data_);
      throw new
        InternalErrorException(Integer.toHexString(ds.getReqRepID()),
                               InternalErrorException.DATA_STREAM_UNKNOWN);
    }
  }  


  // Opens the file for 'read' access, and returns a file handle.
  // If failure, sets errorRC_ and returns UNINITIALIZED.
  private final int createFileHandle()
    throws IOException, AS400SecurityException
  {
    return createFileHandle(IFSOpenReq.READ_ACCESS, IFSOpenReq.OPEN_OPTION_FAIL_OPEN);
  }

  // Opens the file with specified access and option, and returns a file handle.
  // If failure, sets errorRC_ and returns UNINITIALIZED.
  int createFileHandle(int access, int openOption)   // @D1C @B8c
    throws IOException, AS400SecurityException
  {
    int returnCode = IFSReturnCodeRep.FILE_NOT_FOUND;
    int fileHandle = UNINITIALIZED;
    errorRC_ = 0;

    // Try to open the file for the specified type of access.
    try
    {
      // Process an open file request.
      // For 3rd parm (file data CCSID), specify 0 since we don't care about CCSID.
      IFSOpenReq req = new IFSOpenReq(getPathnameAsBytes(), preferredServerCCSID_,
                                      0, access, IFSOpenReq.DENY_NONE,
                                      IFSOpenReq.NO_CONVERSION,
                                      openOption, serverDatastreamLevel_);            // @D1C
      ClientAccessDataStream ds = (ClientAccessDataStream) server_.sendAndReceive(req);
      if (ds instanceof IFSOpenRep)
      {
        // The open was successful.  Close the file if appropriate.
        returnCode = IFSReturnCodeRep.SUCCESS;
        fileHandle = ((IFSOpenRep) ds).getFileHandle();  // @B8a
      }
      else if (ds instanceof IFSReturnCodeRep)
      {
        returnCode = ((IFSReturnCodeRep) ds).getReturnCode();
        throwSecurityExceptionIfAccessDenied(path_,returnCode); // check for "access denied"
      }
      else
      {
        // Unknown data stream.
        Trace.log(Trace.ERROR, "Unknown reply data stream", ds.data_);
        throw new
          InternalErrorException(Integer.toHexString(ds.getReqRepID()),
                                 InternalErrorException.DATA_STREAM_UNKNOWN);
      }
    }
    catch(ConnectionDroppedException e)
    {
      Trace.log(Trace.ERROR, "Byte stream server connection lost", e);
      connectionDropped(e);
    }
    catch(InterruptedException e)
    {
      Trace.log(Trace.ERROR, "Interrupted", e);
      InterruptedIOException throwException = new InterruptedIOException(e.getMessage());
      try {
        throwException.initCause(e); 
      } catch (Throwable t) {} 
      throw throwException;
    }

    if (returnCode != IFSReturnCodeRep.SUCCESS)
    {
      if (Trace.isTraceOn() && Trace.isTraceDiagnosticOn())
      {
        Trace.log(Trace.DIAGNOSTIC, "Unable to open file " + path_ + ": " +
                  "IFSReturnCodeRep return code", descriptionForReturnCode(returnCode));
      }
      errorRC_ = returnCode;
      return UNINITIALIZED;
    }

    return fileHandle;
  }

  /**
   Exchanges server attributes.
   @exception IOException If an error occurs while communicating with the server.
   **/
  void exchangeServerAttributes() // @B2A - code relocated from IFSFileOutputStreamImplRemote,etc.
    throws IOException, AS400SecurityException
  {
      synchronized (serverLock_)
      {
          DataStream ds = server_.getExchangeAttrReply();
          IFSExchangeAttrRep rep = null;
          try { rep = (IFSExchangeAttrRep)ds; }
          catch (ClassCastException e)
          {
            if (ds instanceof IFSReturnCodeRep)
            {
              int rc = ((IFSReturnCodeRep) ds).getReturnCode();
              throwSecurityExceptionIfAccessDenied(path_,rc); // check for "access denied"
              Trace.log(Trace.ERROR, "IFSReturnCodeRep return code", descriptionForReturnCode(rc));
              throw new ExtendedIOException(path_, rc);
            }
            else {
              String className = ( ds == null ? "null" : ds.getClass().getName());
              Trace.log(Trace.ERROR, "Unexpected reply from Exchange Server Attributes: " + className);
              throw new InternalErrorException(InternalErrorException.DATA_STREAM_UNKNOWN);
            }
          }

          // Note: For releases after V5R4, we ask for Datastream Level 16;
          // for V5R3 thru V5R4, we ask for Datastream Level 8;
          // for V4R5 thru V5R2, we ask for Datastream Level 2;
          // for earlier systems, we ask for Datastream Level 0.    // @B6c
          if (getSystemVRM() >= 0x00060100)
            requestedDatastreamLevel_ = 16;
          else if (getSystemVRM() >= 0x00050300)
            requestedDatastreamLevel_ = 8;
          else if (getSystemVRM() >= 0x00040500)                 // @B3A @B4C
            requestedDatastreamLevel_ = 2;
          else
            requestedDatastreamLevel_ = 0;
          if (rep == null)
          {
              ds = null;
              try
              {
                int[] preferredCcsids;        // @A2A
                // Datastream level 8 was introduced in release V5R3.
                if (getSystemVRM() >= 0x00050300)
                { // System is post-V5R2.
                  preferredCcsids = new int[] {0x04b0,0x34b0,0xf200}; // UTF-16, new or old Unicode.
                }
                // Note: Pre-V4R5 systems hang when presented with multiple
                // preferred CCSIDs in the exchange of attributes.   @B3A @B4C
                else if (getSystemVRM() >= 0x00040500)               // @B3A @B4C
                { // System is V4R5 or later.  We can present a list of preferred CCSIDs.
                  preferredCcsids = new int[] {0x34b0,0xf200}; // New or old Unicode.
                }
                else
                { // System is pre-V4R5.  Exchange attr's the old way.
                  preferredCcsids = new int[] {0xf200}; // Old Unicode only.
                }

                // Use GMT date/time, don't use posix style return codes,
                // use PC pattern matching semantics,
                // maximum data transfer size of 0xffffffff.
                ds = server_.sendExchangeAttrRequest( //@B3A
                         new IFSExchangeAttrReq(true, false,
                                                IFSExchangeAttrReq.PC_PATTERN_MATCH,
                                                0xffffffff,
                                                requestedDatastreamLevel_,
                                                preferredCcsids)); // @A2C
                rep = (IFSExchangeAttrRep)ds;
              }
              catch(ConnectionDroppedException e)
              {
                  Trace.log(Trace.ERROR, "Byte stream server connection lost");
                  connectionDropped(e);
              }
              catch(InterruptedException e)
              {
                  Trace.log(Trace.ERROR, "Interrupted", e);
                  system_.disconnectServer(server_);
                  server_ = null;
                  InterruptedIOException throwException = new InterruptedIOException(e.getMessage());
                  try {
                    throwException.initCause(e); 
                  } catch (Throwable t) {} 
                  throw throwException;
              }
              catch(IOException e)
              {
                  Trace.log(Trace.ERROR, "I/O error during attribute exchange.");
                  system_.disconnectServer(server_);
                  server_ = null;
                  throw e;
              }
              catch(ClassCastException e)
              {
                if (ds instanceof IFSReturnCodeRep)
                {
                  int rc = ((IFSReturnCodeRep) ds).getReturnCode();
                  throwSecurityExceptionIfAccessDenied(path_,rc); // check for "access denied"
                  Trace.log(Trace.ERROR, "IFSReturnCodeRep return code", descriptionForReturnCode(rc));
                  throw new ExtendedIOException(path_, rc);
                }
                else {
                  String className = ( ds == null ? "null" : ds.getClass().getName());
                  Trace.log(Trace.ERROR, "Unexpected reply from Exchange Server Attributes: " + className);
                  throw new InternalErrorException(InternalErrorException.DATA_STREAM_UNKNOWN);
                }
              }
          }

          // Process the exchange attributes reply.
          if (rep != null)
          {
              maxDataBlockSize_ = ((IFSExchangeAttrRep) rep).getMaxDataBlockSize();
              preferredServerCCSID_ = rep.getPreferredCCSID();
              serverDatastreamLevel_ = rep.getDataStreamLevel();
              setConverter(ConverterImplRemote.getConverter(preferredServerCCSID_,
                                                                system_));
              if (DEBUG) {
                System.out.println("DEBUG: IFSFileDescriptorImplRemote.exchangeServerAttributes(): " +
                                   "preferredServerCCSID_ == " + preferredServerCCSID_);
                int[] list = rep.getPreferredCCSIDs();
                for (int i=0; i 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;
  }


  /**
   Places a lock on the file at the specified bytes.
   @param offset The first byte of the file to lock (zero is the first byte).
   @param length The number of bytes to lock.
   @return A key for undoing this lock.

   @exception ConnectionDroppedException If the connection is dropped unexpectedly.
   @exception ExtendedIOException If an error occurs while communicating with the server.
   @exception InterruptedIOException If this thread is interrupted.
   @exception ServerStartupException If the server cannot be started.
   @exception UnknownHostException If the system cannot be located.

   @see IFSKey
   @see #unlock
   **/
  IFSKey lock(long length)   // @B2A
    throws IOException, AS400SecurityException
  {
    return lock(fileOffset_, length);
  }

  IFSKey lock(long offset,   // @B2A - code relocated from IFSFileOutputStreamImplRemote,etc.
              long length)
    throws IOException, AS400SecurityException
  {
    // Assume the arguments have been validated by the caller.

    // Attempt to lock the file.
    ClientAccessDataStream ds = null;
    try
    {
      // Issue a mandatory, exclusive lock bytes request.  Mandatory
      // means that the file system enforces the lock by causing any
      // operation which conflicts with the lock to fail.  Exclusive
      // means that only the owner of the lock can read or write the
      // locked area.
      IFSLockBytesReq req =
        new IFSLockBytesReq(fileHandle_, true, false, offset,
                            length, serverDatastreamLevel_);
      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", e);
      InterruptedIOException throwException = new InterruptedIOException(e.getMessage());
      try {
        throwException.initCause(e); 
      } catch (Throwable t) {} 
      throw throwException;
    }

    // Verify the reply.
    if (ds instanceof IFSLockBytesRep)
    {
      int rc = ((IFSLockBytesRep) ds).getReturnCode();
      if (rc != 0)
      {
        Trace.log(Trace.ERROR, "IFSLockBytesRep return code", rc);
        throw new ExtendedIOException(path_, rc);
      }
    }
    else if (ds instanceof IFSReturnCodeRep)
    {
      int rc = ((IFSReturnCodeRep) ds).getReturnCode();
      if (rc != IFSReturnCodeRep.SUCCESS)
      {
        throwSecurityExceptionIfAccessDenied(path_,rc); // check for "access denied"
        Trace.log(Trace.ERROR, "IFSReturnCodeRep return code", descriptionForReturnCode(rc));
        throw new ExtendedIOException(path_, rc);
      }
    }
    else
    {
      // Unknown data stream.
      Trace.log(Trace.ERROR, "Unknown reply data stream", ds.data_);
      throw new
        InternalErrorException(Integer.toHexString(ds.getReqRepID()),
                               InternalErrorException.DATA_STREAM_UNKNOWN);
    }

    // Generate the key for this lock.
    IFSKey key = new IFSKey(fileHandle_, offset, length, true);

    return key;
  }

  // Common code used by IFSFileInputStreamImplRemote and IFSRandomAccessFileImplRemote.
  /**
   Reads up to length bytes of data from this input stream into data,
   starting at the array offset dataOffset.
   @param data The buffer into which the data is read.
   @param offset The start offset of the data in the buffer.
   @param length The maximum number of bytes to read
   @return The total number of bytes read into the buffer, or -1 if there is no more data because the end of file has been reached.

   @exception ConnectionDroppedException If the connection is dropped unexpectedly.
   @exception ExtendedIOException If an error occurs while communicating with the server.
   @exception InterruptedIOException If this thread is interrupted.
   @exception ServerStartupException If the server cannot be started.
   @exception UnknownHostException If the system cannot be located.

   **/
  int read(byte[] data,  // @B2A - code relocated from IFSFileInputStreamImplRemote,etc.
           int    dataOffset,
           int    length)
    throws IOException, AS400SecurityException
  {
    // Assume the arguments have been validated by the public class.

    // If length is zero then return zero.
    if (length == 0)
    {
      return 0;
    }

    int totalBytesRead = 0;
    int bytesRemainingToRead = length;
    boolean endOfFile = false;
    while (totalBytesRead < length && !endOfFile)
    {
      // If the number of bytes being requested is greater than 16 million, then submit multiple requests for smaller chunks.  The File Server has a limit that is somewhat below 16 megabytes (allowing for headers, etc), so 16 _million_ bytes is a safe limit.

      // Issue the read data request.
      int bytesToReadThisTime = Math.min(bytesRemainingToRead, MAX_BYTES_PER_READ);
      IFSReadReq req = new IFSReadReq(fileHandle_, fileOffset_,
                                      bytesToReadThisTime, serverDatastreamLevel_);
      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", e);
        InterruptedIOException throwException = new InterruptedIOException(e.getMessage());
        try {
          throwException.initCause(e); 
        } catch (Throwable t) {} 
        throw throwException;
      }

      // Receive replies until the end of chain.
      boolean endOfChain = false;
      int bytesReadByThisRequest = 0;
      do
      {
        if (ds instanceof IFSReadRep)
        {
          // Copy the data from the reply to the data parameter.
          byte[] buffer = ((IFSReadRep) ds).getData();
          if (buffer.length > 0)
          {
            System.arraycopy(buffer, 0, data, dataOffset, buffer.length);
            bytesReadByThisRequest += buffer.length;
            dataOffset += buffer.length;
          }
          else // no data returned. This implies end-of-file (e.g. if file is empty).
          {
            bytesReadByThisRequest = -1;
            endOfFile = true;
          }
        }
        else if (ds instanceof IFSReturnCodeRep)
        {
          // Check for failure.
          int rc = ((IFSReturnCodeRep) ds).getReturnCode();

          if (rc == IFSReturnCodeRep.SUCCESS)
          {  // It worked, so nothing special to do here.
          }
          else if (rc == IFSReturnCodeRep.NO_MORE_DATA)
          {
            // End of file.
            bytesReadByThisRequest = -1;
            endOfFile = true;
          }
          else  // none of the above
          {
            throwSecurityExceptionIfAccessDenied(path_,rc); // check for "access denied"
            Trace.log(Trace.ERROR, "IFSReturnCodeRep return code", descriptionForReturnCode(rc));
            throw new ExtendedIOException(path_, rc);
          }
        }
        else  // neither IFSReadRep nor IFSReturnCodeRep
        {
          // Unknown data stream.
          Trace.log(Trace.ERROR, "Unknown reply data stream", ds.data_);
          throw new
            InternalErrorException(Integer.toHexString(ds.getReqRepID()),
                                   InternalErrorException.DATA_STREAM_UNKNOWN);
        }

        // Get the next reply if not end of chain.
        endOfChain = ((IFSDataStream) ds).isEndOfChain();
        if (!endOfChain)
        {
          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", e);
            InterruptedIOException throwException = new InterruptedIOException(e.getMessage());
            try {
              throwException.initCause(e); 
            } catch (Throwable t) {} 
            throw throwException;
          }
        }
      }
      while (!endOfChain);

      // Advance the file pointer.
      if (bytesReadByThisRequest > 0) {
        incrementFileOffset(bytesReadByThisRequest);
        totalBytesRead += bytesReadByThisRequest;
        bytesRemainingToRead -= bytesReadByThisRequest;
      }

    }

    // If we have read zero bytes and hit end-of-file, indicate that by returning -1.
    // Otherwise return total number of bytes read.
    return (endOfFile && totalBytesRead == 0 ? -1 : totalBytesRead);
  }

  void setConverter(ConverterImplRemote converter)
  {
    converter_ = converter;
  }


  /**
   Sets the cached "file data CCSID" value.
   **/
  void setCCSID(int ccsid)
    throws IOException
  {
    fileDataCCSID_ = ccsid;
  }

  public void setFileOffset(long fileOffset)
  {
    synchronized(fileOffsetLock_)
    {
      fileOffset_ = fileOffset;
    }
  }


  // @B8a
  boolean setLength(long length)
    throws IOException, AS400SecurityException
  {
    // Assume that we are connected to the server.

    // Prepare to issue a 'change attributes' request.
    ClientAccessDataStream ds = null;

    int fileHandle = UNINITIALIZED;

    try
    {
      // Open the file for read/write, get a file handle, and call 'change attributes'.
      fileHandle = createFileHandle(IFSOpenReq.WRITE_ACCESS, IFSOpenReq.OPEN_OPTION_FAIL_OPEN);
      if (fileHandle == UNINITIALIZED)
      {
        if (Trace.traceOn_) Trace.log(Trace.ERROR, "Unable to create handle to file " + path_ + ". IFSReturnCodeRep return code", errorRC_);
        return false;
      }
      IFSChangeAttrsReq req = new IFSChangeAttrsReq(fileHandle, length, serverDatastreamLevel_);
      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");
      InterruptedIOException throwException = new InterruptedIOException(e.getMessage());
      try {
        throwException.initCause(e); 
      } catch (Throwable t) {} 
      throw throwException;
    }
    finally {
      close(fileHandle);  // we don't need this handle anymore
    }

    // Verify the reply.
    boolean success = false;
    if (ds instanceof IFSReturnCodeRep)
    {
      int rc = ((IFSReturnCodeRep) ds).getReturnCode();
      if (rc == IFSReturnCodeRep.SUCCESS)
        success = true;
      else
      {
        throwSecurityExceptionIfAccessDenied(path_,rc); // check for "access denied"
        Trace.log(Trace.ERROR, path_ + ": IFSReturnCodeRep return code", descriptionForReturnCode(rc));
      }
    }
    else
    {
      // Unknown data stream.
      Trace.log(Trace.ERROR, "Unknown reply data stream", ds.data_);
      throw new
        InternalErrorException(Integer.toHexString(ds.getReqRepID()),
                               InternalErrorException.DATA_STREAM_UNKNOWN);
    }

    // Back off the file pointer if needed.
    if (fileOffset_ > length) {
      fileOffset_ = length;
    }

    return success;
  }


  // Ignores fileHandle if state==false.
  void setOpen(boolean state, int fileHandle)
  {
    if (state == true)
    {
      if (fileHandle == UNINITIALIZED)
      {
        Trace.log(Trace.ERROR, "Called setOpen with invalid file handle: " + fileHandle);
        throw new
          InternalErrorException(InternalErrorException.UNEXPECTED_EXCEPTION);
      }
      else
      {
        if (fileHandle != fileHandle_) close(); // close currently-open handle if different
        fileHandle_ = fileHandle;
      }
    }
    isOpen_ = state;
  }

  void setOpenAllowed(boolean state)
  {
    isOpenAllowed_ = state;
  }

  void setPreferredCCSID(int ccsid)
  {
    preferredServerCCSID_ = ccsid;
  }

  void setServer(AS400Server server)
  {
    server_ = server;
  }

  /**
   Force the system buffers to synchronize with the underlying device.
  **/                                                                      // $A1
  public void sync() throws IOException
  {
    if (parent_ == null)
    {
      Trace.log(Trace.ERROR, "IFSFileDescriptor.sync() was called when parent is null.");
    }
    // Note: UserSpaceImplRemote creates an IFSFileDescriptorImplRemote directly.
    else if (parent_ instanceof IFSRandomAccessFileImplRemote)
    {
      ((IFSRandomAccessFileImplRemote)parent_).flush();
    }
    else if (parent_ instanceof IFSFileOutputStreamImplRemote)
    {
      ((IFSFileOutputStreamImplRemote)parent_).flush();
    }
    else
    {
      Trace.log(Trace.WARNING, "IFSFileDescriptor.sync() was called " +
      "when parent is neither an IFSRandomAccessFile nor an IFSFileOutputStream.");
    }
  }

  private static final void throwSecurityExceptionIfAccessDenied(String path, int returnCode)
    throws AS400SecurityException
  {
    if (returnCode == IFSReturnCodeRep.ACCESS_DENIED_TO_DIR_ENTRY ||
        returnCode == IFSReturnCodeRep.ACCESS_DENIED_TO_REQUEST)
    {
      if (Trace.traceOn_) Trace.log(Trace.DIAGNOSTIC, "Access denied to file " + path + ". " +
                "IFSReturnCodeRep return code", returnCode);
      throw new AS400SecurityException(path, AS400SecurityException.DIRECTORY_ENTRY_ACCESS_DENIED);
    }
  }


  /**
   Undoes a lock on this file.
   @param key The key for the lock.

   @exception IOException If an error occurs while communicating with the server.

   @see IFSKey
   @see #lock
   **/
  void unlock(IFSKey key)  // @B2A - code relocated from IFSFileOutputStreamImplRemote,etc.
    throws IOException, AS400SecurityException
  {
    // Assume the argument has been validated by the caller.

    // Verify that this key is compatible with this file.
    if (key.fileHandle_ != fileHandle_)
    {
      Trace.log(Trace.ERROR, "Attempt to use IFSKey on different file stream.");
      throw new ExtendedIllegalArgumentException("key",
                     ExtendedIllegalArgumentException.PARAMETER_VALUE_NOT_VALID);
    }

    // Attempt to unlock the file.
    ClientAccessDataStream ds = null;
    // Issue an unlock bytes request.
    IFSUnlockBytesReq req =
      new IFSUnlockBytesReq(key.fileHandle_, key.offset_,
                            key.length_, key.isMandatory_, serverDatastreamLevel_);
    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", e);
      InterruptedIOException throwException = new InterruptedIOException(e.getMessage());
      try {
        throwException.initCause(e); 
      } catch (Throwable t) {} 
      throw throwException;
    }

    // Verify the reply.
    if (ds instanceof IFSReturnCodeRep)
    {
      int rc = ((IFSReturnCodeRep) ds).getReturnCode();
      if (rc != IFSReturnCodeRep.SUCCESS)
      {
        throwSecurityExceptionIfAccessDenied(path_,rc); // check for "access denied"
        Trace.log(Trace.ERROR, "IFSReturnCodeRep return code", descriptionForReturnCode(rc));
        throw new ExtendedIOException(path_, rc);
      }
    }
    else
    {
      // Unknown data stream.
      Trace.log(Trace.ERROR, "Unknown reply data stream", ds.data_);
      throw new
        InternalErrorException(Integer.toHexString(ds.getReqRepID()),
                               InternalErrorException.DATA_STREAM_UNKNOWN);
    }
  }


  // Common code used by IFSFileOutputStreamImplRemote and IFSRandomAccessFileImplRemote.
  /**
   Writes length bytes from the byte array data, starting at dataOffset, to this File.
   @param data The data.
   @param dataOffset The start offset in the data.
   @param length The number of bytes to write.
   @parm forceToStorage Whether data must be written before the server replies.

   @exception ConnectionDroppedException If the connection is dropped unexpectedly.
   @exception ExtendedIOException If an error occurs while communicating with the server.
   @exception InterruptedIOException If this thread is interrupted.
   @exception ServerStartupException If the server cannot be started.
   @exception UnknownHostException If the system cannot be located.

   **/
  void writeBytes(byte[]  data,     // @B2A
                  int     dataOffset,
                  int     length)
    throws IOException, AS400SecurityException
  {
    writeBytes(data, dataOffset, length, false);
  }
  void writeBytes(byte[]  data,  // @B2A - code relocated from IFSFileOutputStreamImplRemote,etc.
                  int     dataOffset,
                  int     length,
                  boolean forceToStorage)
    throws IOException, AS400SecurityException
  {
    // Assume the arguments have been validated by the caller.

    // Send write requests until all data has been written.
    while(length > 0)
    {
      // Determine how much data can be written on this request.
      int writeLength = (length > maxDataBlockSize_ ?
                         maxDataBlockSize_ : length);

      // Build the write request.  Set the chain bit if there is
      // more data to write.
      IFSWriteReq req = new IFSWriteReq(fileHandle_, fileOffset_,
                                        data, dataOffset, writeLength,
                                        0xffff, forceToStorage, serverDatastreamLevel_);
      if (length - writeLength > 0)
      {
        // Indicate that there is more to write.
        req.setChainIndicator(1);
      }

      // Send the request.
      ClientAccessDataStream ds = null;
      try
      {
        // Send the request and receive the response.
        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", e);
        InterruptedIOException throwException = new InterruptedIOException(e.getMessage());
        try {
          throwException.initCause(e); 
        } catch (Throwable t) {} 
        throw throwException;
      }

      // Check the reply.
      if (ds instanceof IFSWriteRep)
      {
        IFSWriteRep rep = (IFSWriteRep) ds;
        int rc = rep.getReturnCode();
        if (rc != 0)
        {
          Trace.log(Trace.ERROR, "IFSWriteRep return code", rc);
          throw new ExtendedIOException(path_, rc);
        }

        // Advance the file pointer the length of the data
        // written.
        int lengthWritten = writeLength - rep.getLengthNotWritten();
        incrementFileOffset(lengthWritten);
        dataOffset += lengthWritten;
        length -= lengthWritten;

        // Ensure that all data requested was written.
        if (lengthWritten != writeLength)
        {
          Trace.log(Trace.ERROR, "Incomplete write.  Only " +
                    Integer.toString(lengthWritten) + " bytes of a requested " +
                    Integer.toString(writeLength) + " were written.");
          throw new ExtendedIOException(path_, ExtendedIOException.UNKNOWN_ERROR);
        }
      }
      else if (ds instanceof IFSReturnCodeRep)
      {
        int rc = ((IFSReturnCodeRep) ds).getReturnCode();
        if (rc != IFSReturnCodeRep.SUCCESS)
        {
          throwSecurityExceptionIfAccessDenied(path_,rc); // check for "access denied"
          Trace.log(Trace.ERROR, "IFSReturnCodeRep return code", descriptionForReturnCode(rc));
          throw new ExtendedIOException(path_, rc);
        }
      }
      else
      {
        // Unknown data stream.
        Trace.log(Trace.ERROR, "Unknown reply data stream", ds.data_);
        throw new
          InternalErrorException(Integer.toHexString(ds.getReqRepID()),
                                 InternalErrorException.DATA_STREAM_UNKNOWN);
      }
    }
  }
  public int getServerDatastreamLevel() {
    return serverDatastreamLevel_;
  }
  
  //@V4A
  public int createUserHandle() throws IOException, AS400SecurityException{
    ClientAccessDataStream ds = null;
    int UserHandle = UNINITIALIZED;
    int rc;
    byte[] ClientSeed = BinaryConverter.longToByteArray(System.currentTimeMillis());
    byte[] ServerSeed = null;
    try {
      IFSUserHandleSeedReq req = new IFSUserHandleSeedReq(ClientSeed);
      ds = (ClientAccessDataStream) server_.sendAndReceive(req);
    }
    catch(InterruptedException e)
    {
      Trace.log(Trace.ERROR, "Interrupted");
      InterruptedIOException throwException = new InterruptedIOException(e.getMessage());
      try {
        throwException.initCause(e); 
      } catch (Throwable t) {} 
      throw throwException;
    }
    // Verify that we got a handle back.
    if (ds instanceof IFSUserHandleSeedRep)
    {
      ServerSeed = ((IFSUserHandleSeedRep) ds).getSeed();
    }
    else if (ds instanceof IFSReturnCodeRep)
    {
      rc = ((IFSReturnCodeRep) ds).getReturnCode();
      if (rc != IFSReturnCodeRep.SUCCESS)
      {
        Trace.log(Trace.ERROR, "IFSReturnCodeRep return code", rc);
      }
      throw new ExtendedIOException(rc);
    }
    else
    {
      // Unknown data stream.
      Trace.log(Trace.ERROR, "Unknown reply data stream",
                ds.getReqRepID());
      throw new
        InternalErrorException(Integer.toHexString(ds.getReqRepID()),
                               InternalErrorException.DATA_STREAM_UNKNOWN);
    }
    
    
    rc = 0;
    ds = null;
    byte[] userIDbytes = SignonConverter.stringToByteArray(system_.getUserId());
    byte[] encryptedPassword = system_.getPassword(ClientSeed, ServerSeed);
    IFSCreateUserHandlerReq req = new IFSCreateUserHandlerReq(userIDbytes, encryptedPassword);
    try {
      ds = (ClientAccessDataStream) server_.sendAndReceive(req);
    } catch (InterruptedException e) {
      Trace.log(Trace.ERROR, "Interrupted");
      InterruptedIOException throwException = new InterruptedIOException(e.getMessage());
      try {
        throwException.initCause(e); 
      } catch (Throwable t) {} 
      throw throwException;
    }

    // Verify the reply.
    if (ds instanceof IFSCreateUserHandleRep)
    {
      rc = ((IFSCreateUserHandleRep)ds).getReturnCode();
      if (rc != IFSReturnCodeRep.SUCCESS)
      {
        Trace.log(Trace.ERROR, "IFSCreateUserHandleRep return code", rc);
      }
      UserHandle = ((IFSCreateUserHandleRep) ds).getHandle();
      
    }
    else if (ds instanceof IFSReturnCodeRep)
    {
      rc = ((IFSReturnCodeRep) ds).getReturnCode();
      if (rc != IFSReturnCodeRep.SUCCESS)
      {
        Trace.log(Trace.ERROR, "IFSReturnCodeRep return code", rc);
      }
      throw new ExtendedIOException(rc);
    }
    else
    {
      // Unknown data stream.
      Trace.log(Trace.ERROR, "Unknown reply data stream",
                ds.getReqRepID());
      throw new
        InternalErrorException(InternalErrorException.DATA_STREAM_UNKNOWN,
                               Integer.toHexString(ds.getReqRepID()),null);
    }
    return UserHandle;
  
  }
  
  public void freeUserHandle(int userHandle) throws IOException, AS400SecurityException{
    IFSFreeUserHandlerReq req = new IFSFreeUserHandlerReq(userHandle);
    server_.send(req);
  }
  
  public void freeHandle(int objectHandle) throws IOException, AS400SecurityException{
    IFSFreeHandleReq req = new IFSFreeHandleReq(objectHandle);
    server_.send(req);
  }
  
   //@AC7A Start
  public int getASP(boolean isDirectory) throws IOException, AS400SecurityException {
	  isDirectory_ = isDirectory;
	  return getASP();
  }
  //@AC7A End
  
  public int getASP() throws IOException, AS400SecurityException {
    if (fileAsp_ == UNINITIALIZED)
    { 
      ClientAccessDataStream ds = null;
      int rc = 0;

      connect();

      // Ensure that we are connected to the server.
      byte[] pathname = getConverter().stringToByteArray(path_);

      //create user handle
      int userHandle = UNINITIALIZED, objectHandle = UNINITIALIZED;
      try{
        userHandle = system_.createUserHandle();
        try
        {
          // Issue a Look up request to create an object handle.
          //IFSLookupReq req = new IFSLookupReq(pathname, preferredServerCCSID_, userHandle, IFSLookupReq.OA1, IFSLookupReq.ASP_FLAG, 0);
        	IFSLookupReq req = new IFSLookupReq(pathname, preferredServerCCSID_, userHandle, IFSLookupReq.OA12, IFSObjAttrs1.OWNERANAME_ASP_FLAS, 0); //@AC7A 
        	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");
          InterruptedIOException throwException = new InterruptedIOException(e.getMessage());
          try {
            throwException.initCause(e); 
          } catch (Throwable t) {} 
          throw throwException;
        }

        rc = 0;
        if (ds instanceof IFSLookupRep)
        {
          objectHandle = ((IFSLookupRep) ds).getHandle();
          //fileAsp_ = ((IFSLookupRep) ds).getASP();  //@AC7D
          retrieveAttributes(ds, objectHandle);  //@AC7A 
        }
        else if (ds instanceof IFSReturnCodeRep)
        {
          rc = ((IFSReturnCodeRep) ds).getReturnCode();
          if (rc != IFSReturnCodeRep.SUCCESS)
          {
            Trace.log(Trace.ERROR, "IFSReturnCodeRep return code", rc);
          }
          throw new ExtendedIOException(path_, rc);
        }
        else
        {
          // Unknown data stream.
          Trace.log(Trace.ERROR, "Unknown reply data stream",
              ds.getReqRepID());
          throw new
          InternalErrorException(Integer.toHexString(ds.getReqRepID()),
              InternalErrorException.DATA_STREAM_UNKNOWN);
        }
      }finally{
        //if(userHandle != UNINITIALIZED)
         // freeUserHandle(userHandle);
        if(objectHandle != UNINITIALIZED)
          freeHandle(objectHandle);
      }
    }

    return fileAsp_;
  }
  
//@AC7A Start
  public String getOwnerNameByUserHandle(boolean forceRetrieve) throws IOException, AS400SecurityException {
	  Trace.log(Trace.INFORMATION, "Owner Name " + (fileOwnerName_ == null? "is null" : fileOwnerName_));
	  isDirectory_ = true;
	  if (forceRetrieve || fileOwnerName_ == null) {
		  Trace.log(Trace.INFORMATION, "force retrieve for Owner Name.");
		  fileOwnerName_ = getOwnerNameByUserHandle();
	  }
	  return fileOwnerName_;
  }
//@AC7A End

  public String getOwnerNameByUserHandle() throws IOException, AS400SecurityException {
    //String ownerName = null; //@AC7D 
    ClientAccessDataStream ds = null;
    int rc = 0;

    // Ensure that we are connected to the server.
    connect();
    byte[] pathname = getConverter().stringToByteArray(path_);
    
    //create user handle
    int userHandle = UNINITIALIZED, objectHandle = UNINITIALIZED;
    try{
      userHandle = system_.createUserHandle();
      try
      {
        // Issue a Look up request to create an object handle.
        //IFSLookupReq req = new IFSLookupReq(pathname, preferredServerCCSID_, userHandle, IFSLookupReq.OA1, IFSObjAttrs1.OWNER_NAME_FLAG, 0); //@AC7A End
    	  IFSLookupReq req = new IFSLookupReq(pathname, preferredServerCCSID_, userHandle, IFSLookupReq.OA12, IFSObjAttrs1.OWNERANAME_ASP_FLAS, 0); //@AC7A 
    	  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");
        InterruptedIOException throwException = new InterruptedIOException(e.getMessage());
        try {
          throwException.initCause(e); 
        } catch (Throwable t) {} 
        throw throwException;
      }

      // Verify that we got a handle back.
      rc = 0;
      if (ds instanceof IFSLookupRep)
      {
        //ownerName = ((IFSLookupRep) ds).getOwnerName(system_.getCcsid());  //@AC7A End
        objectHandle = ((IFSLookupRep) ds).getHandle();
        retrieveAttributes(ds, objectHandle);  //@AC7A
      }
      else if (ds instanceof IFSReturnCodeRep)
      {
        rc = ((IFSReturnCodeRep) ds).getReturnCode();
        if (rc != IFSReturnCodeRep.SUCCESS)
        {
          Trace.log(Trace.ERROR, "IFSReturnCodeRep return code", rc);
        }
        throw new ExtendedIOException(path_, rc);
      }
      else
      {
        // Unknown data stream.
        Trace.log(Trace.ERROR, "Unknown reply data stream",
            ds.getReqRepID());
        throw new
        InternalErrorException(Integer.toHexString(ds.getReqRepID()),
            InternalErrorException.DATA_STREAM_UNKNOWN);
      }
    }finally{
     // if(userHandle != UNINITIALIZED)
       // freeUserHandle(userHandle);
      if(objectHandle != UNINITIALIZED)
        freeHandle(objectHandle);
    }
    //return (ownerName == null ? "" : ownerName);  //@AC7D 
    return (fileOwnerName_ == null ? "" : fileOwnerName_);  //@AC7A 
  }
  
//@AC7A Start
  public String getFileSystemType(boolean isDirectory) throws IOException, AS400SecurityException {
	  isDirectory_ = isDirectory;
	  return getFileSystemType();
  }
//@AC7A End
  
  public String getFileSystemType() throws IOException, AS400SecurityException {
    String typeString = "Unknown";
    
    if (fileSystemType_ == UNINITIALIZED)
    {
      ClientAccessDataStream ds = null;
      int rc = 0;
      connect();

      int objectHandle = UNINITIALIZED;
      byte[] pathname = getConverter().stringToByteArray(path_);

      //create user handle
      int userHandle = UNINITIALIZED;
      try{
        userHandle = system_.createUserHandle();
        try
        {
          // Issue a Look up request to create an object handle.
          //IFSLookupReq req = new IFSLookupReq(pathname, preferredServerCCSID_, userHandle); //@AC7D
        	IFSLookupReq req = new IFSLookupReq(pathname, preferredServerCCSID_, userHandle, IFSLookupReq.OA12, IFSObjAttrs1.OWNERANAME_ASP_FLAS, 0); //@AC7A Start
          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");
          InterruptedIOException throwException = new InterruptedIOException(e.getMessage());
          try {
            throwException.initCause(e); 
          } catch (Throwable t) {} 
          throw throwException;
        }

        rc = 0;
        if (ds instanceof IFSLookupRep)
        {
          objectHandle = ((IFSLookupRep) ds).getHandle();
          retrieveAttributes(ds, objectHandle); //@AC7A 
        }
        else if (ds instanceof IFSReturnCodeRep)
        {
          rc = ((IFSReturnCodeRep) ds).getReturnCode();
          if (rc != IFSReturnCodeRep.SUCCESS)
          {
            Trace.log(Trace.ERROR, "IFSReturnCodeRep return code", rc);
          }
          throw new ExtendedIOException(path_, rc);
        }
        else
        {
          // Unknown data stream.
          Trace.log(Trace.ERROR, "Unknown reply data stream",
              ds.getReqRepID());
          throw new
          InternalErrorException(Integer.toHexString(ds.getReqRepID()),
              InternalErrorException.DATA_STREAM_UNKNOWN);
        }

        /* //@AC7D Start
        ds = null;
        try
        {
          // Issue a get file system request.
          IFSGetFileSystemReq req = new IFSGetFileSystemReq(objectHandle, userHandle);
          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");
          InterruptedIOException throwException = new InterruptedIOException(e.getMessage());
          try {
            throwException.initCause(e); 
          } catch (Throwable t) {} 
          throw throwException;
        }

        // Verify the reply.
        rc = 0;
        if (ds instanceof IFSGetFileSystemRep)
        {
          fileSystemType_ = ((IFSGetFileSystemRep) ds).getFileSystemType();
        }
        else if (ds instanceof IFSReturnCodeRep)
        {
          rc = ((IFSReturnCodeRep) ds).getReturnCode();
          if (rc != IFSReturnCodeRep.SUCCESS)
          {
            Trace.log(Trace.ERROR, "IFSReturnCodeRep return code", rc);
          }
          throw new ExtendedIOException(path_, rc);
        }
        else
        {
          // Unknown data stream.
          Trace.log(Trace.ERROR, "Unknown reply data stream",
              ds.getReqRepID());
          throw new
          InternalErrorException(InternalErrorException.DATA_STREAM_UNKNOWN,
              Integer.toHexString(ds.getReqRepID()),null);
        }
        */ //@AC7D Start
      }finally{
        //if(userHandle != UNINITIALIZED)
         // freeUserHandle(userHandle);
        if(objectHandle != UNINITIALIZED)
          freeHandle(objectHandle);
      }
    }
    switch(fileSystemType_) {
        case 1 : typeString = "EPFS"; break;
        case 2 : typeString = "QDLS"; break;
        case 3 : typeString = "QSYS"; break;
        case 4 : typeString = "NFS"; break;
        case 5 : typeString = "LRFS"; break;
        case 6 : typeString = "QOPT"; break;
        case 7 : typeString = "QRFS"; break;
        case 9 : typeString = "EPFSP"; break;
        case 11 : typeString = "QNETC"; break;
        case 12 : typeString = "QDTL"; break;
        case 13 : typeString = "IEPFS"; break;
        case 14 : typeString = "ASPQSYS"; break;
    }
    return typeString;
  }

  //@AC7A Start
  private void retrieveAttributes(ClientAccessDataStream ds, int objectHandle) throws IOException, AS400SecurityException {
		  fileAsp_ = ((IFSLookupRep) ds).getASP();
		  //if (isDirectory_) { @AE8D
			  fileOwnerName_ = ((IFSLookupRep) ds).getOwnerName(system_.getCcsid());
			  fileDataCCSID_ = ((IFSLookupRep) ds).getCCSID(serverDatastreamLevel_);
		  //}
		  int userHandle = system_.getUserHandle();		 
		  int rc = 0;
		  ds = null;
	        try
	        {
	          // Issue a get file system request.
	          IFSGetFileSystemReq req = new IFSGetFileSystemReq(objectHandle, userHandle);
	          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");
	          InterruptedIOException throwException = new InterruptedIOException(e.getMessage());
	          try {
	            throwException.initCause(e); 
	          } catch (Throwable t) {} 
	          throw throwException;
	        }

	        // Verify the reply.
	        rc = 0;
	        if (ds instanceof IFSGetFileSystemRep)
	        {
	          fileSystemType_ = ((IFSGetFileSystemRep) ds).getFileSystemType();
	        }
	        else if (ds instanceof IFSReturnCodeRep)
	        {
	          rc = ((IFSReturnCodeRep) ds).getReturnCode();
	          if (rc != IFSReturnCodeRep.SUCCESS)
	          {
	            Trace.log(Trace.ERROR, "IFSReturnCodeRep return code", rc);
	          }
	          throw new ExtendedIOException(path_, rc);
	        }
	        else
	        {
	          // Unknown data stream.
	          Trace.log(Trace.ERROR, "Unknown reply data stream",
	              ds.getReqRepID());
	          throw new
	          InternalErrorException(InternalErrorException.DATA_STREAM_UNKNOWN,
	              Integer.toHexString(ds.getReqRepID()),null);
	        }
  }
  //@AC7A End

}








© 2015 - 2024 Weber Informatics LLC | Privacy Policy