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

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

There is a newer version: 20.0.7
Show newest version
///////////////////////////////////////////////////////////////////////////////
//                                                                             
// JTOpen (IBM Toolbox for Java - OSS version)                              
//                                                                             
// Filename: AS400FileImplBase.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-2004 International Business Machines Corporation and     
// others. All rights reserved.                                                
//                                                                             
///////////////////////////////////////////////////////////////////////////////

package com.ibm.as400.access;

import java.io.IOException;
import java.util.Enumeration;
import java.util.Vector;
import java.beans.PropertyVetoException;
import java.math.BigDecimal;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; //@F0A

abstract class AS400FileImplBase implements AS400FileImpl, Cloneable //@B5C
{
  // Is this class an ImplRemote or an ImplNative
  boolean isNative_ = false; //@E2A

  boolean discardReplys_ = false; //@D1A (moved out of AS400FileImplRemote)

  // Converter that converts to the server job CCSID.
  ConverterImplRemote converter_; //@B5C

  // retrieve the requested record, do not consider deleted records as
  // part of the file
  static final byte DATA_DTA_DTARCD = 0;
  // position the file to the requested record, do not
  // retrieve the data, do not consider deleted records
  static final byte DATA_NODTA_DTARCD = 1;
  // GET
  static final byte OPER_GET = 1;
  // GETD
  static final byte OPER_GETD = 2;
  // GETK
  static final byte OPER_GETK = 3;
  // PUTDR
  static final byte OPER_PUTDR = 4;
  // PUT
  static final byte OPER_PUT = 5;
  // UPDATE
  static final byte OPER_UPDATE = 7;
  // DELETE
  static final byte OPER_DELETE = 8;
  // FEOD
  static final byte OPER_FEOD = 9;
  // retrieve for read only
  static final byte SHR_READ_NORM = 0;
  // retrieve for read only and give up lock on previously locked record
  static final byte SHR_READ_NORM_RLS = 2;
  // retrieve for update
  static final byte SHR_UPD_NORM = 3;
  // retrieve the record for read leaving the previous
  // file position as the current file position
  static final byte SHR_READ_NOPOS = 0x10;
  // retrieve for read only leaving the previous file position as the
  // current file position and give up lock on previously locked record
  static final byte SHR_READ_NOPOS_RLS = 0x12;
  // retrieve the record for update leaving the previous
  // file position as the current file position after the get request
  static final byte SHR_UPD_NOPOS = 0x13;
  // retrieve for update but do not wait on record locks
  // held by the same process
  static final byte SHR_UPD_NORM_NW = 0x23;
  // retrieve the record for update leaving the previous file position as
  // the current file position after the get request but do not wait on
  // record locks held by the same process
  static final byte SHR_UPD_NOPOS_NW = 0x33;
  // retrieve first record
  static final byte TYPE_GET_FIRST = 1;
  // retrieve last record
  static final byte TYPE_GET_LAST = 2;
  // retrieve next record
  static final byte TYPE_GET_NEXT = 3;
  // retrieve previous record
  static final byte TYPE_GET_PREV = 4;
  // retrieve current record
  static final byte TYPE_GET_SAME = 0x21;
  // Retrieve record at the specified position (relative to file start).
  static final byte TYPE_GETD_ABSRRN = 8;
  // WDMHLIB
  private static final int WDMHLIB = 72;
  // WDMHMBR
  private static final int WDMHMBR = 73;

  // Open feedback information from open().
  DDMS38OpenFeedback openFeedback_;

  // The following String constants are used to format the DDS source when
  // creating a file from a user supplied RecordFormat object
  static final String STR16 = "                ";
  static final String STR18 = "                  ";
  static final String STR44 = "                                            ";

  // Indicates which explicit locks, if any, have been obtained.  There are six
  // possible types of locks.  Initially each array element is false.
  Vector explicitLocksObtained_ = new Vector(6);

  // Servers currently under commitment control.
  static Vector commitmentControlSystems_ = new Vector();

  // Used for commitment control when we're running natively. See AS400FileImplBase.
  static boolean nativeCommitmentControlStarted_ = false; //@E2A

  //@B0A: These are duplicated from the public class since they are either
  //      beans or parts of beans.
  AS400ImplRemote system_ = null; //@B5C
  String name_ = null;
  RecordFormat recordFormat_ = null;
  String library_ = null;
  String file_ = null;
  String member_ = null;

  // Holds any cached records
  DDMRecordCache cache_ = new DDMRecordCache();
  // Indicates if records are to be cached; if blockingFactor_ > 1 and file
  // is not opened for READ_WRITE, records will be cached.
  boolean cacheRecords_ = false;

  // Caches the record formats retrieved from the server for the file
  RecordFormat[] rfCache_ = null; //@B2A

  // The lock level for commitment control for this file.  This value is
  // specified upon construction of the object if commitment control has been
  // started for the connection.
  int commitLockLevel_ = -1;

  // The number of records to retrieve during a read operation or the maximum
  // number of records to write at one time during a writeCollection()
  int blockingFactor_;

  // A boolean indicating if it's a 'read no update' in an open type of read/write.
  // If 'read no update' is true, it allows a file to be opened as read/write, yet
  // reading won't exclusively lock the records being read. The default is false.
  boolean readNoUpdate_ = false;

  // Indicates if this file should be treated as an SSP file or DDM file
  // when createUFCB() is called.
  boolean ssp_ = false;

  // Manner in which file has been opened.  This value will be set upon open().
  // -1 indicates that the file is not open.
  int openType_ = -1;

  // These two variables are used to do the CTLL name conversion once after the
  // file is opened so that the converion result can be directly used in later
  // DDM request streams.
  byte[] recordFormatCTLLName_ = null;
  private String recordFormatName_ = "";

  //@B0A
  // This flag tells us if we are an impl for a KeyedFile or a SequentialFile.
  // Created primarily for use in refreshCache().
  //private boolean isKeyed_ = false;      // not used


  //@B4A - constants for comparing keys
  private static final int EQUAL = 1; // keys are equal
  private static final int LESS_THAN = 2; // search key < current key
  private static final int GREATER_THAN = 3; // search key > current key
  private static final int UNKNOWN = 4; // Not equal, but keep searching.

  private static final boolean CHECK_LENGTHS = true;  // mnemonic for flag-setting

  public void doIt(String methodName, Class[] classes, Object[] objects)
  throws AS400Exception, AS400SecurityException, InterruptedException, IOException
  {
    try
    {
      invoke(this, methodName, classes, objects); //@F0C
    }
    catch (InvocationTargetException e)
    {
      throw rethrow(e);
    }
    catch (Exception e2)
    {
      Trace.log(Trace.ERROR, e2.toString(), e2);
      throw new InternalErrorException(InternalErrorException.PROTOCOL_ERROR, e2);
    }
  }

  // Rethrows exceptions returned as InvocationTargetExceptions.  This provides some common exception handling.
  // @param  e  The InvocationTargetException.
  // @return  An InternalErrorException if the exception is not known.
  // @throws  The exception.
  public static InternalErrorException rethrow(InvocationTargetException e) throws AS400Exception, AS400SecurityException, InterruptedException, IOException
  {
    Throwable e2 = e.getTargetException();
    if (e2 instanceof AS400Exception) {
      throw (AS400Exception)e2;
    }
    else if (e2 instanceof InterruptedException) {
      throw (InterruptedException)e2;
    }
    else if (e2 instanceof AS400SecurityException) {
      throw (AS400SecurityException)e2;
    }
    else if (e2 instanceof IOException) {
      throw (IOException)e2;
    }
    else if (e2 instanceof RuntimeException) {
      throw (RuntimeException)e2;
    }
    else if (e2 instanceof Error) {
      throw (Error)e2;
    }
    else return new InternalErrorException(InternalErrorException.UNEXPECTED_EXCEPTION, e2);
  }

  public void doItNoExceptions(String methodName, Class[] classes, Object[] objects)
  {
    try
    {
      invoke(this, methodName, classes, objects); //@F0C
    }
    catch (Exception e2)
    {
      Trace.log(Trace.ERROR, e2.toString(), e2);
      throw new InternalErrorException(InternalErrorException.PROTOCOL_ERROR, e2);
    }
  }

  public Record doItRecord(String methodName, Class[] classes, Object[] objects)
  throws AS400Exception, AS400SecurityException, InterruptedException, IOException
  {
    try
    {
      return(Record)invoke(this, methodName, classes, objects); //@F0C
    }
    catch (InvocationTargetException e)
    {
      throw rethrow(e);
    }
    catch (Exception e2)
    {
      Trace.log(Trace.ERROR, e2.toString(), e2);
      throw new InternalErrorException(InternalErrorException.PROTOCOL_ERROR, e2);
    }
  }

  public Record[] doItRecordArray(String methodName, Class[] classes, Object[] objects)
  throws AS400Exception, AS400SecurityException, InterruptedException, IOException
  {
    try
    {
      return(Record[])invoke(this, methodName, classes, objects); //@F0C
    }
    catch (InvocationTargetException e)
    {
      throw rethrow(e);
    }
    catch (Exception e2)
    {
      Trace.log(Trace.ERROR, e2);
      throw new InternalErrorException(InternalErrorException.PROTOCOL_ERROR, e2);
    }
  }

  //@B2A
  public RecordFormat doItRecordFormat(String methodName, Class[] classes, Object[] objects)
  throws AS400Exception, AS400SecurityException, InterruptedException, IOException
  {
    try
    {
      return(RecordFormat)invoke(this, methodName, classes, objects); //@F0C
    }
    catch (InvocationTargetException e)
    {
      throw rethrow(e);
    }
    catch (Exception e2)
    {
      Trace.log(Trace.ERROR, e2);
      throw new InternalErrorException(InternalErrorException.PROTOCOL_ERROR, e2);
    }
  }

  public int doItInt(String methodName)
  {
    try
    {
      return((Integer)invoke(this, methodName, new Class[0], new Object[0])).intValue(); //@F0C
    }
    catch (Exception e)
    {
      Trace.log(Trace.ERROR, e);
      throw new InternalErrorException(InternalErrorException.PROTOCOL_ERROR, e);
    }
  }

  public boolean doItBoolean(String methodName)
  {
    try
    {
      return((Boolean)invoke(this, methodName, new Class[0], new Object[0])).booleanValue(); //@F0C
    }
    catch (Exception e)
    {
      Trace.log(Trace.ERROR, e);
      throw new InternalErrorException(InternalErrorException.PROTOCOL_ERROR, e);
    }
  }

  //@E2A
  public boolean doItBoolean(String methodName, Class[] classes, Object[] objects)
  {
    try
    {
      return((Boolean)invoke(this, methodName, classes, objects)).booleanValue(); //@F0C
    }
    catch (Exception e)
    {
      Trace.log(Trace.ERROR, e);
      throw new InternalErrorException(InternalErrorException.PROTOCOL_ERROR, e);
    }
  }


  //@F0A - This method is copied from PxMethodReqSV. We don't
  // want to have dependencies on the proxy classes directly, so
  // that's why I included it here.
  static Object invoke(Object object, 
                       String methodName, 
                       Class[] argumentClasses,
                       Object[] arguments)
  throws ClassNotFoundException, 
  IllegalAccessException,
  InvocationTargetException, 
  NoSuchMethodException
  {      
    // Resolve the Method object.  First, try Class.getMethod() which 
    // only looks for public methods.  If that does not work, try 
    // Class.getDeclaredMethod(), which only looks for declared 
    // methods (not inherited methods).  Do this up the superclass tree.
    Method method = null;
    Class clazz = object.getClass();
    NoSuchMethodException e = null;
    while ((clazz != null) && (method == null))
    {
      try
      {
        method = clazz.getMethod(methodName, argumentClasses);
      }
      catch (NoSuchMethodException e1)
      {
        try
        {
          method = clazz.getDeclaredMethod(methodName, argumentClasses);
        }
        catch (NoSuchMethodException e2)
        {
          e = e2;
          clazz = clazz.getSuperclass();
        }
      }
    }
    if (method == null)
      throw e;

    // Call the method.
    return method.invoke (object, arguments);
  }


  //public void setIsKeyed(boolean keyed)   // not used
  //{
  //  isKeyed_ = keyed;
  //}

  public boolean isReadNoUpdate()
  {
    return readNoUpdate_;
  }


  //@B0A
  /**
   *Adds a physical file member to the file represented by this object.
   *@param name The name of the member to create.  The name cannot
   *exceed 10 characters in length.  The name cannot be null.
   *@param textDescription The text description with which to create the file.
   *This value must be 50 characters or less.  If this value is null, the
   *text description will be blank.
*The name of the file and the server to which to connect must be set *prior to invoking this method. *@see AS400File#AS400File(com.ibm.as400.access.AS400, java.lang.String) *@see AS400File#setPath *@see AS400File#setSystem *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception ConnectionDroppedException If the connection is dropped * unexpectedly. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the * server. *@exception ServerStartupException If the host server cannot be started. **/ public void addPhysicalFileMember(String name, String textDescription) throws AS400Exception, AS400SecurityException, InterruptedException, IOException { // Create the ADDPFM command string StringBuffer cmd = new StringBuffer("QSYS/ADDPFM FILE("); cmd.append(library_); cmd.append("/"); cmd.append(file_); cmd.append(") MBR("); cmd.append(name); cmd.append(") TEXT("); // Determine correct text description and add it to the command string if (textDescription == null) { // No text description supplied. cmd.append(AS400File.BLANK); //@B3C cmd.append(")"); //@B3A } else if (textDescription.length() == 0 || textDescription.equalsIgnoreCase(AS400File.BLANK)) //@A3C { // Empty string passed for text or special value *BLANK specified cmd.append(AS400File.BLANK); //@B3C cmd.append(")"); //@B3A } else { // Enclose the text description in single quotes for the command cmd.append("'"); cmd.append(textDescription); cmd.append("')"); } // Add the member. AS400Message[] msgs = execute(cmd.toString()); //@B0C if (!(msgs.length > 0 && msgs[0].getID().equals("CPC7305"))) { throw new AS400Exception(msgs); } } // Compare 2 arrays, returning the relationship of first array to second array. private final static int compareArrays(byte[] array1, byte[] array2, boolean checkLengths) { if (checkLengths) { if (array1.length < array2.length) return LESS_THAN; if (array1.length > array2.length) return GREATER_THAN; } // Compare the arrays, byte by byte. for (int k = 0; k < array1.length; ++k) { if (array1[k] < array2[k]) return LESS_THAN; if (array1[k] > array2[k]) return GREATER_THAN; } return EQUAL; } //@B4C /** *Determines if the keys are the same. *@param key key to compare *@param recKey key of record being compared to *@return The result of the key comparison (EQUAL, GREATER_THAN, LESS_THAN, or UNKNOWN). * For example, GREATER_THAN indicates that 'key' is greater than 'recKey'. **/ private int compareKeys(Object[] key, Object[] recKey) { if (key.length > recKey.length) { // Key is greater in length than recKey; not valid if (Trace.isTraceOn() && Trace.isTraceErrorOn()) { Trace.log(Trace.WARNING, "compareKeys: Search key has too many fields."); } return UNKNOWN; } // Key has possibilities - may be a partial key, or may be a full key // so we only check matches up to the length of the "key" passed in. int match = EQUAL; for (int j = 0; j < key.length && match == EQUAL; ++j) { if (key[j] instanceof byte[] && recKey[j] instanceof byte[]) { byte[] searchKey = (byte[])key[j]; byte[] recordKey = (byte[])recKey[j]; match = compareArrays(searchKey, recordKey, CHECK_LENGTHS); } else if (recordFormat_.getKeyFieldDescription(j) instanceof VariableLengthFieldDescription) // superclass of all textual field types { //@B4C -- begin // Note: A String in a DDM field is always padded with blanks // to be the length of the field. // Therefore, we should ignore any trailing blanks in the keys, // but we must regard any leading ones. String searchKey = (String)key[j]; String recordKey = (String)recKey[j]; int searchKeyLength = searchKey.length(); int recordKeyLength = recordKey.length(); if (searchKeyLength < recordKeyLength) { // pad the search key with trailing blanks StringBuffer buf = new StringBuffer(searchKey); for (int i=searchKeyLength; i recordKeyLength) { // It is OK for the user to pass in a blank-padded search // key that is longer than the length of the field. // We just chop it to be the correct length. searchKey = searchKey.substring(0, recordKeyLength); } // Note: We must account for the system CCSID when comparing text fields, since the records on the system will be sorted according to the system CCSID, which may result in a different collation than in Unicode. For example, in some CCSIDs, '1' precedes 'A', whereas in other CCSIDs, 'A' precedes '1'. // To honor the CCSID-specific collation, first convert the keys to system bytes before comparing them. FieldDescription fd = recordFormat_.getKeyFieldDescription(j); byte[] searchKeyAsBytes = fd.getDataType().toBytes(searchKey); byte[] recordKeyAsBytes = fd.getDataType().toBytes(recordKey); match = compareArrays(searchKeyAsBytes, recordKeyAsBytes, CHECK_LENGTHS); //@B4C -- end } else if (key[j] instanceof BigDecimal && recKey[j] instanceof BigDecimal) { // decimal field BigDecimal searchKey = (BigDecimal)key[j]; BigDecimal recordKey = (BigDecimal)recKey[j]; int res = searchKey.compareTo(recordKey); if (res > 0) match = GREATER_THAN; else if (res < 0) match = LESS_THAN; } else if (!key[j].equals(recKey[j])) { // some other type // Since we don't know the type, we have to keep searching // the whole file. match = UNKNOWN; } } return match; } //@B4C // @A2A /** *Determines if the keys are the same. *@param key key in bytes to compare *@param recKey key of record in bytes being compared to *@param numberOfKeyFields The number of key fields contained in the byte array key *being compared to recKey. The number of key fields must be greater than 0 and less *than the total number of key fields in the record format for this file. *@return The result of the key comparison (EQUAL, GREATER_THAN, LESS_THAN, or UNKNOWN). * For example, GREATER_THAN indicates that 'key' is greater than 'recKey'. **/ private int compareKeys(byte[] key, byte[] recKey, int numberOfKeyFields) { if (key.length > recKey.length) { // Key is greater in length than recKey; not valid if (Trace.isTraceOn() && Trace.isTraceErrorOn()) { Trace.log(Trace.WARNING, "compareKeys: Search key is too long."); } return UNKNOWN; } if ((numberOfKeyFields < 1) || (numberOfKeyFields > recordFormat_.getNumberOfKeyFields())) { throw new ExtendedIllegalArgumentException("numberOfKeyFields", ExtendedIllegalArgumentException.PARAMETER_VALUE_NOT_VALID); } // Check to see if the byte length of 'key' is valid on a per key field basis. int keyByteLength = 0; FieldDescription[] fd = recordFormat_.getKeyFieldDescriptions(); for (int i=0; i *
  • READ_EXCLUSIVE_LOCK *
  • READ_ALLOW_SHARED_READ_LOCK *
  • READ_ALLOW_SHARED_WRITE_LOCK *
  • WRITE_EXCLUSIVE_LOCK *
  • WRITE_ALLOW_SHARED_READ_LOCK *
  • WRITE_ALLOW_SHARED_WRITE_LOCK * *If no explicit locks have been obtained for the file, an array of size zero *is returned. **/ public int[] getExplicitLocks() { // Create an array of the explicit locks that are currently set. int[] locks = new int[explicitLocksObtained_.size()]; for (int i = 0; i < locks.length; i++) { locks[i] = ((Integer) explicitLocksObtained_.elementAt(i)).intValue(); } return locks; } public int getOpenType() { return openType_; } /** *Closes the file on the server. *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the *server. **/ public void close() //@B0C -- this method is overridden by the subclasses throws AS400Exception, AS400SecurityException, InterruptedException, IOException { // Shut down any caching cacheRecords_ = false; cache_.setIsEmpty(); // Reset the blocking factor blockingFactor_ = 0; // Reset the open type. -1 indicates that the file is not open openType_ = -1; // Reset the commit lock level. commitLockLevel_ = (isCommitmentControlStarted() ? AS400File.COMMIT_LOCK_LEVEL_NONE : -1 ); } /** * This is a convenience method for setting all 4 properties at once, so as to * avoid 4 separate proxy calls. * @param system * @param pathName * @param rf * @param readNoUpdate * @param isKeyed * @param ssp * @throws IOException If an error occurs while communicating with the system. **/ public void setAll(AS400Impl system, String pathName, RecordFormat rf, boolean readNoUpdate, boolean isKeyed, boolean ssp) //@B5C throws IOException //@B5A - 06/08/1999 { setSystem(system); setPath(pathName); setRecordFormat(rf); setReadNoUpdate(readNoUpdate); //@B5A //setIsKeyed(isKeyed); setSSPFile(ssp); setConverter(); //@B5A - 06/08/1999 } /** *Commits all transactions since the last commit boundary. Invoking this *method will cause all transactions under commitment control for this *connection to be committed. *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the *server. **/ public abstract void commit() throws AS400Exception, AS400SecurityException, InterruptedException, IOException; //@E2A // This method should be static, but we can't make a static call to // a native method (the call to execute()) so we just set all of the // necessary state variables and act like we're a normal object. public void commit(AS400Impl system) throws AS400Exception, AS400SecurityException, InterruptedException, IOException { if (isCommitmentControlStarted(system)) { // Setup state variables setSystem(system); setConverter(); commit(); } } //@B0A public void setConverter() throws IOException { converter_ = ConverterImplRemote.getConverter(system_.getCcsid(), system_); //@B5C //@E0D if (recordFormat_ != null) recordFormat_.setConverter(converter_); //@D0A } public void setPath(String name) { // Construct a QSYSObjectPathName object and parse out the library, // file and member names QSYSObjectPathName ifs = new QSYSObjectPathName(name); if (!(ifs.getObjectType().equals("FILE") || ifs.getObjectType().equals("MBR"))) { // Invalid object type throw new IllegalPathNameException(name, IllegalPathNameException.OBJECT_TYPE_NOT_VALID); } // Set the instance data as appropriate library_ = ifs.getLibraryName(); file_ = ifs.getObjectName(); if (ifs.getObjectType().equals("FILE")) { // No member specified; default member to *FIRST member_ = "*FIRST"; } else { // Member specified; if special value %FILE% was specified, member name // is the file name member_ = (ifs.getMemberName().equalsIgnoreCase("*FILE") ? file_ : ifs.getMemberName()); } name_ = name; rfCache_ = null; //@B2A } public void setReadNoUpdate(boolean readNoUpdate) { readNoUpdate_ = readNoUpdate; } //@B2A /** * Retrieves rfCache_[rf]. If the cache is empty, retrieves the record * formats from the server. * @param rf * @return recordFormat * @throws AS400Exception If an error occurs. * @throws AS400SecurityException If a security or authority error occurs. * @throws InterruptedException If this thread is interrupted. * @throws IOException If an error occurs while communicating with the system. **/ public RecordFormat setRecordFormat(int rf) throws AS400Exception, AS400SecurityException, InterruptedException, IOException { if (rfCache_ == null) { AS400FileRecordDescriptionImplRemote desc = new AS400FileRecordDescriptionImplRemote(); //@B5C desc.setPath(name_); //@B5A desc.setSystem(system_); //@B5A rfCache_ = desc.retrieveRecordFormat(); } if (rfCache_.length <= rf) // the index is too big { throw new ExtendedIllegalArgumentException("recordFormat (" + String.valueOf(rf) + ") too large", ExtendedIllegalArgumentException.RANGE_NOT_VALID); } return rfCache_[rf]; } //@B2A /** * Retrieves "rf" from rfCache_. If the cache is empty, retrieves the record * formats from the server. * @param rf * @return recordFormat * @throws AS400Exception If an error occurs. * @throws AS400SecurityException If a security or authority error occurs. * @throws InterruptedException If this thread is interrupted. * @throws IOException If an error occurs while communicating with the system. **/ public RecordFormat setRecordFormat(String rf) throws AS400Exception, AS400SecurityException, InterruptedException, IOException { if (rfCache_ == null) { AS400FileRecordDescriptionImplRemote desc = new AS400FileRecordDescriptionImplRemote(); //@B5C desc.setPath(name_); //@B5A desc.setSystem(system_); //@B5A rfCache_ = desc.retrieveRecordFormat(); } RecordFormat toSet = null; for (int i=0; i 10) rfName = rfName.substring(0, 10); converter_.stringToByteArray(rfName, ufcb, offset + 6); for (int i = rfName.length(); i < 10 && i+offset+6 < ufcb.length; i++) { ufcb[i + offset + 6] = 0x40; } offset += 16; } // Indicate the end of the variable portion of the UFCB; this is required BinaryConverter.unsignedShortToByteArray(32767, ufcb, offset); return ufcb; } /** *Deletes the record at the current cursor position. The file must be open and *the cursor must be positioned on an active record. *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ public abstract void deleteCurrentRecord() throws AS400Exception, AS400SecurityException, InterruptedException, IOException; /** *Deletes the member associated with this object from the file. The object cannot *be open when invoking this method.
    *The name of the file and the server to which to connect must be set prior *to invoking this method. *@see AS400File#AS400File(com.ibm.as400.access.AS400, java.lang.String) *@see AS400File#setPath *@see AS400File#setSystem *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception ConnectionDroppedException If the connection is dropped unexpectedly. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. *@exception ServerStartupException If the host server cannot be started. **/ public void deleteMember() throws AS400Exception, AS400SecurityException, InterruptedException, IOException { AS400Message[] msgs = execute("QSYS/RMVM FILE(" + library_ + "/" + //@B0C file_ + ") MBR(" + member_ + ")"); if (msgs.length > 0 && msgs[0].getID() != null) { if (!msgs[0].getID().equals("CPC7309")) { throw new AS400Exception(msgs); } } else { Trace.log(Trace.ERROR, "No messages from server"); throw new InternalErrorException(InternalErrorException.UNKNOWN); } } //@D1A /** * Turns on reply discarding for the data streams. * This is only used when our public object is being finalized. **/ public void discardReplies() { discardReplys_ = true; } /** *Ends commitment control for this connection. *If commitment control has not been started for the connection, no action *is taken. *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception ConnectionDroppedException If the connection is dropped unexpectedly. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ public void endCommitmentControl() throws AS400Exception, AS400SecurityException, InterruptedException, IOException { endCommitmentControl(system_); //@E2A /*@E2D if (isCommitmentControlStarted()) { AS400Message[] msgs = execute("QSYS/ENDCMTCTL"); //@B0C if (msgs.length > 0 && msgs[0].getID() != null && !msgs[0].getID().equals("CPI8351")) { throw new AS400Exception(msgs); } // Remove the current system from the list of commitment control // systems. commitmentControlSystems_.removeElement(system_); // server_.commitmentControlStarted_ = false; //@B0A } */ //@E2D } //@E2A // This method should be static, but we can't make a static call to // a native method (the call to execute()) so we just set all of the // necessary state variables and act like we're a normal object. public void endCommitmentControl(AS400Impl system) throws AS400Exception, AS400SecurityException, InterruptedException, IOException { synchronized(commitmentControlSystems_) { if ((isNative_ && nativeCommitmentControlStarted_) || // native case commitmentControlSystems_.contains(system)) // remote case { // Setup state variables setSystem(system); setConverter(); // End commitment control AS400Message[] msgs = execute("QSYS/ENDCMTCTL"); if (msgs.length > 0 && msgs[0].getID() != null && !msgs[0].getID().equals("CPI8351")) { throw new AS400Exception(msgs); } if (isNative_) { nativeCommitmentControlStarted_ = false; } else { commitmentControlSystems_.removeElement(system_); } } } } /** *Starts commitment control on this file (for this connection). If commitment control *has already been started for the connection, an exception is thrown. *@param commitLockLevel The type of commitment control * to exercise. Valid values are: *
      *
    • COMMIT_LOCK_LEVEL_ALL *
    • COMMIT_LOCK_LEVEL_CHANGE *
    • COMMIT_LOCK_LEVEL_CURSOR_STABILITY *
    *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception ConnectionDroppedException If the connection is dropped unexpectedly. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. *@exception ServerStartupException If the host server cannot be started. **/ public void startCommitmentControl(int commitLockLevel) throws AS400Exception, AS400SecurityException, InterruptedException, IOException { startCommitmentControl(system_, commitLockLevel); //@E2A /*@E2D // Build the command to start commitment control. StringBuffer cmd = new StringBuffer("QSYS/STRCMTCTL LCKLVL(*"); switch(commitLockLevel) { case AS400File.COMMIT_LOCK_LEVEL_CHANGE: cmd.append("CHG)"); break; case AS400File.COMMIT_LOCK_LEVEL_CURSOR_STABILITY: cmd.append("CS)"); break; case AS400File.COMMIT_LOCK_LEVEL_ALL: cmd.append("ALL)"); break; default: throw new ExtendedIllegalArgumentException("commitLockLevel", ExtendedIllegalArgumentException.PARAMETER_VALUE_NOT_VALID); } // Start commitment control. AS400Message[] msgs = execute(cmd.toString()); //@B0C if (msgs.length > 0 && msgs[0].getID() != null) { if (!msgs[0].getID().equals("CPI8351")) { throw new AS400Exception(msgs); } } // Indicate that commitment control is started for the current system. // server_.commitmentControlStarted_ = true; if (!commitmentControlSystems_.contains(system_)) { commitmentControlSystems_.addElement(system_); } */ //@E2D } //@E2A // This method should be static, but we can't make a static call to // a native method (the call to execute()) so we just set all of the // necessary state variables and act like we're a normal object. public void startCommitmentControl(AS400Impl system, int commitLockLevel) throws AS400Exception, AS400SecurityException, InterruptedException, IOException { synchronized(commitmentControlSystems_) { if ((isNative_ && nativeCommitmentControlStarted_) || // native case commitmentControlSystems_.contains(system)) // remote case { // AS400Impl that was passed in must be natively connected // or we would never have been instantiated as an AS400FileImplNative. // The AS400.loadImpl() method makes sure of that. // We just check a boolean flag in the ImplNative... no need to add // it to the Vector, since there should only ever be one "connection" // for an ImplNative. // If we're an ImplRemote, we just check the Vector like usual. throw new ExtendedIllegalStateException(ExtendedIllegalStateException.COMMITMENT_CONTROL_ALREADY_STARTED); } // Setup state variables setSystem(system); setConverter(); // Build the command to start commitment control. StringBuffer cmd = new StringBuffer("QSYS/STRCMTCTL LCKLVL(*"); switch (commitLockLevel) { case AS400File.COMMIT_LOCK_LEVEL_CHANGE: cmd.append("CHG)"); break; case AS400File.COMMIT_LOCK_LEVEL_CURSOR_STABILITY: cmd.append("CS)"); break; case AS400File.COMMIT_LOCK_LEVEL_ALL: cmd.append("ALL)"); break; default: throw new ExtendedIllegalArgumentException("commitLockLevel", ExtendedIllegalArgumentException.PARAMETER_VALUE_NOT_VALID); } // Start commitment control. AS400Message[] msgs = execute(cmd.toString()); if (msgs.length > 0 && msgs[0].getID() != null) { if (!msgs[0].getID().equals("CPI8351")) { throw new AS400Exception(msgs); } } // Indicate that commitment control is started for the current system. if (isNative_) { nativeCommitmentControlStarted_ = true; } else if (!commitmentControlSystems_.contains(system_)) { commitmentControlSystems_.addElement(system_); } } } /** *Resets the state instance variables of this object to the appropriate *values for the file being closed. This method is used to reset the *the state of the object when the connection has been ended abruptly. **/ public synchronized void resetState() { // Shut down any caching cacheRecords_ = false; cache_.setIsEmpty(); // Reset the blocking factor blockingFactor_ = 0; // Reset the open type. -1 indicates that the file is not open openType_ = -1; // Reset the commit lock level; as this method is only called if the // connection was ended abruptly, there is no server, so there is no // need to check if commitment control has been started. commitLockLevel_ = -1; } /** *Releases all locks acquired via the lock() method. If no locks have been *explicitly obtained, no action is taken. *@see AS400File#lock *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception ConnectionDroppedException If the connection is dropped unexpectedly. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. *@exception ServerStartupException If the host server cannot be started. **/ public void releaseExplicitLocks() throws AS400Exception, AS400SecurityException, InterruptedException, IOException { if (explicitLocksObtained_.size() > 0) { // Build the command to release the explicit locks. StringBuffer cmd = new StringBuffer("QSYS/DLCOBJ OBJ("); for (Enumeration e = explicitLocksObtained_.elements(); e.hasMoreElements();) { cmd.append("("); cmd.append(library_); cmd.append("/"); cmd.append(file_); cmd.append(" *FILE "); int lockType = ((Integer)e.nextElement()).intValue(); switch (lockType) { case AS400File.READ_ALLOW_SHARED_READ_LOCK: cmd.append("*SHRNUP "); break; case AS400File.READ_ALLOW_SHARED_WRITE_LOCK: cmd.append("*SHRRD "); break; case AS400File.READ_EXCLUSIVE_LOCK: case AS400File.WRITE_EXCLUSIVE_LOCK: cmd.append("*EXCL "); break; case AS400File.WRITE_ALLOW_SHARED_READ_LOCK: cmd.append("*EXCLRD "); break; case AS400File.WRITE_ALLOW_SHARED_WRITE_LOCK: cmd.append("*SHRUPD "); break; default: Trace.log(Trace.ERROR, "Unrecognized lock type: " + lockType); throw new InternalErrorException(InternalErrorException.UNKNOWN, lockType); } cmd.append(member_); cmd.append(") "); } cmd.append(")"); // Execute the command. AS400Message[] msgs = execute(cmd.toString()); //@B0C if (msgs.length > 0 && msgs[0].getID() != null) { throw new AS400Exception(msgs); } // Clear the list of explicit locks. explicitLocksObtained_.removeAllElements(); } } /** *Executes a command on the server. *@param cmd the command *@exception AS400SecurityException If a security or authority error occurs. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ public abstract AS400Message[] execute(String cmd) throws AS400SecurityException, InterruptedException, IOException; /** *Returns the commit lock level for this file as specified on open. *@return The commit lock level for this file. *If commitment control has not been started for the connection or if *file has not been opened, -1 is returned. *Possible return values are: *
      *
    • COMMIT_LOCK_LEVEL_ALL *
    • COMMIT_LOCK_LEVEL_CHANGE *
    • COMMIT_LOCK_LEVEL_CURSOR_STABILITY *
    • COMMIT_LOCK_LEVEL_DEFAULT *
    • COMMIT_LOCK_LEVEL_NONE *
    • -1 *
    **/ public int getCommitLockLevel() { return(isCommitmentControlStarted() ? commitLockLevel_ : -1); } /** *Indicates if commitment control is started for *the connection. *@return true if commitment control has been started; false otherwise. **/ public boolean isCommitmentControlStarted() { if (isNative_) //@E2A return nativeCommitmentControlStarted_; //@E2A else //@E2A return commitmentControlSystems_.contains(system_); // return (server_ != null ? server_.commitmentControlStarted_ : false); //@B0A } //@E2A // This method should be static, but we can't make a static call to // a native method (the call to execute()) so we just set all of the // necessary state variables and act like we're a normal object. public boolean isCommitmentControlStarted(AS400Impl system) { if (isNative_) return nativeCommitmentControlStarted_; else return commitmentControlSystems_.contains(system); } /** *Creates a physical file with the specified record length and file type. *The record format for this object will be set by this method. The *record format for the file is determined as follows: *
      *
    • If fileType is AS400File.TYPE_DATA, *
        *
      • The format name of the file is the name of the file as specified on the *constructor *
      • The record format contains one field whose name is the name of the file, *whose type is CHARACTER, and whose length is recordLength *
      *
    • If fileType is AS400File.TYPE_SOURCE, *
        *
      • The format name of the file is the name of the file as specified on the *constructor *
      • The record format contains three fields: *
          *
        • SRCSEQ whose type is ZONED(6, 2) *
        • SRCDAT whose type is ZONED(6, 0) *
        • SRCDTA whose type is CHARACTER and whose length is *recordLength - 12 *
        *
      *
    *Note: The file is created using the default values for the * Create Physical File command (CRTPF). * Use the CommandCall class to issue a CHGPF * command to change the file after it *has been created.
    *The name of the file and the server to which to connect must be set prior *to invoking this method. *@see AS400File#AS400File(com.ibm.as400.access.AS400, java.lang.String) *@see AS400File#setPath *@see AS400File#setSystem *@param recordLength The record length with which to create the file. Valid values * are 1 through 32766 inclusive. *@param fileType The file type with which to create the file. Valid values are * AS400File.TYPE_DATA or AS400File.TYPE_SOURCE. If AS400File.TYPE_DATA is specified, the record * format for the file contains one field. If AS400File.TYPE_SOURCE is * specified, the record format for the file contains three * fields: source sequence number, date, and source statement. *@param textDescription The text description with which to create the file. *This value must be between 1 and 50 characters inclusive. *If this value is null, the empty string, or AS400File.BLANK, *the text description is blank. *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception ConnectionDroppedException If the connection is dropped unexpectedly. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. *@exception ServerStartupException If the host server cannot be started. **/ public void create(int recordLength, String fileType, String textDescription) throws AS400Exception, AS400SecurityException, InterruptedException, IOException { // Create the CRTPF command string StringBuffer cmd = new StringBuffer("QSYS/CRTPF FILE("); cmd.append(library_); cmd.append("/"); cmd.append(file_); cmd.append(") RCDLEN("); cmd.append(recordLength); cmd.append(") MBR("); cmd.append(member_); cmd.append(") TEXT("); // Determine correct text description if (textDescription == null) { // Specify *BLANK for text on the command cmd.append(AS400File.BLANK); //@B3C } else if (textDescription.length() == 0 || textDescription.equalsIgnoreCase(AS400File.BLANK)) //@B3C { // Specify *BLANK for text on the command cmd.append(AS400File.BLANK); //@B3C } else { // Enclose the text description in single quotes for the command cmd.append("'"); cmd.append(textDescription); cmd.append("'"); } cmd.append(") FILETYPE("); cmd.append(fileType); cmd.append(")"); // Create the file. AS400Message[] msgs = execute(cmd.toString()); //@B0C if (!(msgs.length > 0 && msgs[0].getID().equals("CPC7301"))) { throw new AS400Exception(msgs); } } /** *Creates a physical file using the specified DDS source file. *Note: The file is created using the default values for the * Create Physical File (CRTPF) command. *Use the CommandCall class to issue a CHGPF to change the file after it *has been created.
    *The name of the file and the server to which to connect must be set prior *to invoking this method. *@see AS400File#AS400File(com.ibm.as400.access.AS400, java.lang.String) *@see AS400File#setPath *@see AS400File#setSystem *@param ddsSourceFile The integrated file system pathname of the file containing the *DDS source for the file being created. *@param textDescription The text description with which to create the file. *This value must be between 1 and 50 characters inclusive. *If this value is null, the empty string, or AS400File.BLANK, *the text description will be blank. *Specify AS400File.SOURCE_MEMBER_TEXT for the text description if the text *description from ddsSourceFile is to be used. *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception ConnectionDroppedException If the connection is dropped unexpectedly. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. *@exception ServerStartupException If the host server cannot be started. **/ public void create(String ddsSourceFile, String textDescription) throws AS400Exception, AS400SecurityException, InterruptedException, IOException { // Parse the ddsDourceFile into library, file and member QSYSObjectPathName ifs = new QSYSObjectPathName(ddsSourceFile); if (!(ifs.getObjectType().equals("FILE") || ifs.getObjectType().equals("MBR"))) { // Invalid QSYSObjectPathName throw new IllegalPathNameException(ddsSourceFile, IllegalPathNameException.OBJECT_TYPE_NOT_VALID); } // Create the CRTPF command string StringBuffer cmd = new StringBuffer("QSYS/CRTPF FILE("); cmd.append(library_); cmd.append("/"); cmd.append(file_); cmd.append(") SRCFILE("); cmd.append(ifs.getLibraryName()); cmd.append("/"); cmd.append(ifs.getObjectName()); cmd.append(") SRCMBR("); cmd.append(ifs.getMemberName()); cmd.append(") MBR("); if (member_.equals("*FIRST")) { // *FIRST is not a valid value for CRTPF MBR(). if (Trace.traceOn_) Trace.log(Trace.DIAGNOSTIC, "Setting MBR to *FILE."); cmd.append("*FILE"); } else cmd.append(member_); cmd.append(") TEXT("); // Determine correct text description if (textDescription == null) { // Specify *BLANK for text on the command cmd.append(AS400File.BLANK); //@B3C cmd.append(")"); //@B3A } else if (textDescription.length() == 0 || textDescription.equalsIgnoreCase(AS400File.BLANK)) //@A3C { // Specify *BLANK for text on the command cmd.append(AS400File.BLANK); //@B3C cmd.append(")"); //@B3A } else if (textDescription.equalsIgnoreCase(AS400File.SOURCE_MEMBER_TEXT)) //@B3C { cmd.append(textDescription); cmd.append(")"); } else { // Enclose the text description in single quotes for the command cmd.append("'"); cmd.append(textDescription); cmd.append("')"); } // Create the file. AS400Message[] msgs = execute(cmd.toString()); //@B0C if (!(msgs.length > 0 && msgs[0].getID().equals("CPC7301"))) { throw new AS400Exception(msgs); } } /** *Creates the DDS source file to be used to create a physical file based on a user *supplied RecordFormat.
    *The name of the file and the server to which to connect must be set prior *to invoking this method. *@see AS400File#AS400File(com.ibm.as400.access.AS400, java.lang.String) *@see AS400File#setPath *@see AS400File#setSystem *@param recordFormat The record format to describe in the DDS source file. *@param altSeq The value to be specified for the file-level keyword ALTSEQ. If no *value is to be specified, null may be specified. *@param ccsid The value to be specified for the file-level keyword CCSID. If no *value is to be specified, null may be specified. *@param order The value to be specified to indicate in which order records are to be *retrieved from the file. Valid values are one of the following file-level keywords: *
      *
    • FIFO - First in, first out *
    • LIFO - Last in, first out *
    • FCFO - First changed, first out *
    *If no ordering value is to be specified, null may be specified. *@param ref The value to be specified for the file-level keyword REF. If no *value is to be specified, null may be specified. *@param unique Indicates if the file-level keyword UNIQUE is to be specified. True *indicates that the UNIQUE keyword should be specified; false indicates that it *should not be specified. *@param format The value to be specified for the record-level keyword FORMAT. If no *value is to be specified, null may be specified. *@param text The value to be specified for the record-level keyword TEXT. If no *value is to be specified, null may be specified. *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception ConnectionDroppedException If the connection is dropped unexpectedly. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. *@exception ServerStartupException If the host server cannot be started. */ public abstract void createDDSSourceFile(RecordFormat recordFormat, //@D0C 7/15/99 @E1C String altSeq, String ccsid, String order, String ref, boolean unique, String format, String text) throws AS400Exception, AS400SecurityException, InterruptedException, IOException; //@D0 7/15/99 - made abstract and moved code into ImplRemote /** *Deletes the file. The object cannot be open when calling this method. The file *and all its members will be deleted. *Use deleteMember() to delete only the member associated with this object.
    *The name of the file and the server to which to connect must be set prior *to invoking this method. *@see AS400File#AS400File(com.ibm.as400.access.AS400, java.lang.String) *@see AS400File#setPath *@see AS400File#setSystem *@see AS400File#deleteMember *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception ConnectionDroppedException If the connection is dropped unexpectedly. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. *@exception ServerStartupException If the host server cannot be started. **/ public void delete() throws AS400Exception, AS400SecurityException, InterruptedException, IOException { AS400Message[] msgs = execute("QSYS/DLTF FILE(" + library_ + "/" + //@B0C file_ + ")"); if (msgs.length > 0) { if (msgs[0].getID() != null && !msgs[0].getID().equals("CPC2191")) { throw new AS400Exception(msgs); } } else { Trace.log(Trace.ERROR, "No messages from server"); throw new InternalErrorException(InternalErrorException.UNKNOWN); } } /** *Obtains a lock on the file. *The name of the file and the server to which to connect must be set prior *to invoking this method. *@see AS400File#AS400File(com.ibm.as400.access.AS400, java.lang.String) *@see AS400File#setPath *@see AS400File#setSystem *@param lockToObtain The type of lock to acquire on the file. * Valid lock values are: *
      *
    • READ_EXCLUSIVE_LOCK *
    • READ_ALLOW_SHARED_READ_LOCK *
    • READ_ALLOW_SHARED_WRITE_LOCK *
    • WRITE_EXCLUSIVE_LOCK *
    • WRITE_ALLOW_SHARED_READ_LOCK *
    • WRITE_ALLOW_SHARED_WRITE_LOCK *
    *If lockToObtain has already been obtained, no action is taken. *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception ConnectionDroppedException If the connection is dropped unexpectedly. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. *@exception ServerStartupException If the host server cannot be started. */ public void lock(int lockToObtain) throws AS400Exception, AS400SecurityException, InterruptedException, IOException { Integer l = new Integer(lockToObtain); if (!explicitLocksObtained_.contains(l)) { // Lock the file using the ALCOBJ command. StringBuffer cmd = new StringBuffer("QSYS/ALCOBJ OBJ(("); cmd.append(library_); cmd.append("/"); cmd.append(file_); cmd.append(" *FILE "); switch (lockToObtain) { case AS400File.READ_ALLOW_SHARED_READ_LOCK: cmd.append("*SHRNUP "); break; case AS400File.READ_ALLOW_SHARED_WRITE_LOCK: cmd.append("*SHRRD "); break; case AS400File.READ_EXCLUSIVE_LOCK: case AS400File.WRITE_EXCLUSIVE_LOCK: cmd.append("*EXCL "); break; case AS400File.WRITE_ALLOW_SHARED_READ_LOCK: cmd.append("*EXCLRD "); break; case AS400File.WRITE_ALLOW_SHARED_WRITE_LOCK: cmd.append("*SHRUPD "); break; default: throw new InternalErrorException(InternalErrorException.UNKNOWN, lockToObtain); } cmd.append(member_); cmd.append("))"); AS400Message[] msgs = execute(cmd.toString()); //@B0C if (msgs.length > 0 && msgs[0].getID() != null) { throw new AS400Exception(msgs); } // Indicate which lock has been obtained explicitLocksObtained_.addElement(l); } } /** *Opens the file. Helper function to open file for keyed or *sequential files. *@param openType *@param bf blocking factor *@param access The type of file access for which to open the file. *@return the open feedback data *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ public abstract DDMS38OpenFeedback openFile(int openType, int bf, String access) throws AS400Exception, AS400SecurityException, InterruptedException, IOException; //@B0A - need this for compatibility with the remote and native impls public String[] openFile2(int openType, int blockingFactor, int commitLockLevel, String access) throws AS400Exception, AS400SecurityException, InterruptedException, IOException { return openFile2(openType, blockingFactor, commitLockLevel, access.equals("key")); } public String[] openFile2(int openType, int blockingFactor, int commitLockLevel, boolean access) //@B0C throws AS400Exception, AS400SecurityException, InterruptedException, IOException { commitLockLevel_ = (isCommitmentControlStarted() ? commitLockLevel : -1); /*@D0M // Set the blocking factor for the file if (openType != AS400File.READ_WRITE) { // Calculate the blocking factor if 0 was specified if (blockingFactor == 0) { blockingFactor_ = calculateBlockingFactor(); } else { blockingFactor_ = blockingFactor; } // Estimate the record increment. int recordIncrement = recordFormat_.getNewRecord().getRecordLength() + recordFormat_.getNumberOfFields() + recordFormat_.getNumberOfKeyFields() + 16; // We can only retrieve 16Mb of record data per GET so limit the // blocking factor appropriately. blockingFactor_ = (blockingFactor_ * recordIncrement >= 16777216 ? 16777216 / recordIncrement : blockingFactor_); } else { // For open type of READ_WRITE or if the file is a KeyedFile, blocking // factor is set to 1 for data integrity // reasons (read_write implies we are reading and updating and therefore // want up-to-date data. blockingFactor_ = 1; } */ //@D0M blockingFactor_ = blockingFactor; //@D0A // Determine if we are to cache records. cacheRecords_ = (blockingFactor_ > 1); // @A5A // Set the record format CTLL name if (!recordFormatName_.equals(recordFormat_.getName())) { recordFormatName_ = recordFormat_.getName(); StringBuffer recordName = new StringBuffer(recordFormat_.getName()); while (recordName.length() < 10) recordName.append(' '); ConverterImplRemote c = ConverterImplRemote.getConverter(system_.getCcsid(), system_); //@B5C recordFormatCTLLName_ = c.stringToByteArray(recordName.toString()); } // Open the file. DDMS38OpenFeedback openFeedback = openFile(openType, blockingFactor_, access ? "key" : "seq"); //@B0C - access is true for KeyedFiles // Set the open type openType_ = openType; String[] toReturn = new String[2]; //@B0A // If a special value was specified for library or member, set the actual name // now. Note that the server returns the names blank padded to ten characters // so we trim off any blanks. if (library_.charAt(0) == '*') { library_ = openFeedback.getLibraryName().trim(); toReturn[0] = library_; //@B0A } if (member_.equalsIgnoreCase("*FIRST") || member_.equalsIgnoreCase("*LAST")) { member_ = openFeedback.getMemberName().trim(); toReturn[1] = member_; //@B0A } return toReturn; } /** *Positions the file cursor to the first record whose record number *matches the specified record number. The file must be open when invoking *this method. *@param recordNumber The record number of the record at which to position the *cursor. *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception ConnectionDroppedException If the connection is dropped unexpectedly. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ public void positionCursor(int recordNumber) throws AS400Exception, AS400SecurityException, InterruptedException, IOException { // If caching, check if position is in the cache. If it is not, refresh the // the cache and position appropriately. if (cacheRecords_) { if (!cache_.setPosition(recordNumber)) { positionCursorToIndex(recordNumber); } } else { // Not caching positionCursorToIndex(recordNumber); } } //@RBA public void positionCursorLong(long recordNumber) throws AS400Exception, AS400SecurityException, InterruptedException, IOException { // If caching, check if position is in the cache. If it is not, refresh the // the cache and position appropriately. if (cacheRecords_) { if (!cache_.setPositionLong(recordNumber)) { positionCursorToIndexLong(recordNumber); } } else { // Not caching positionCursorToIndexLong(recordNumber); } } /** *Positions the file cursor to the first record meeting the specified search criteria *based on key. The searchType indicates that the cursor should be *positioned to the record whose key first meets the search criteria when compared *to key. The file must be open when invoking this method. *@param key The values that make up the key with which to find the record. *The key must contain at least one element. The types and order of *the elements that make up key must match the type and order of the *key fields in the record format for this object. Null values for key fields *are not supported. *@param searchType Constant indicating the type of match required. Valid values are: *
      *
    • KEY_EQ
      *First record whose key is equal to key. *
    • KEY_LT
      *First record whose key is less than key. *
    • KEY_LE
      *First record whose key is less than or equal to key. *
    • KEY_GT
      *First record whose key is greater than key. *
    • KEY_GE
      *First record whose key is greater than or equal to key. *
    *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception ConnectionDroppedException If the connection is dropped unexpectedly. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ public void positionCursor(Object[] key, int searchType) throws AS400Exception, AS400SecurityException, InterruptedException, IOException { positionCursorToKey(key, searchType); // Invalidate the cache if (cacheRecords_) { cache_.setIsEmpty(); } } //@RBA public void positionCursorLong(Object[] key, int searchType) throws AS400Exception, AS400SecurityException, InterruptedException, IOException { positionCursorToKeyLong(key, searchType); // Invalidate the cache if (cacheRecords_) { cache_.setIsEmpty(); } } /** *Positions the file cursor to the first record meeting the specified search criteria *based on key. The searchType indicates that the cursor should be *positioned to the record whose key first meets the search criteria when compared *to key. The file must be open when invoking this method. *@param key The byte array that contains the byte values that make up the key with which to find the record. *The byte array key must contain the byte values from at least one key field. The types and order of *the elements that make up key must match the type and order of the *key fields in the record format for this object. Null values for key fields *are not supported. *@param searchType Constant indicating the type of match required. Valid values are: *
      *
    • KEY_EQ
      *First record whose key is equal to key. *
    • KEY_LT
      *First record whose key is less than key. *
    • KEY_LE
      *First record whose key is less than or equal to key. *
    • KEY_GT
      *First record whose key is greater than key. *
    • KEY_GE
      *First record whose key is greater than or equal to key. *
    *@param numberOfKeyFields The number of key fields contained in the byte array key. *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception ConnectionDroppedException If the connection is dropped unexpectedly. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ public void positionCursor(byte[] key, int searchType, int numberOfKeyFields) throws AS400Exception, AS400SecurityException, InterruptedException, IOException { positionCursorToKey(key, searchType, numberOfKeyFields); // Invalidate the cache if (cacheRecords_) { cache_.setIsEmpty(); } } //@RBA public void positionCursorLong(byte[] key, int searchType, int numberOfKeyFields) throws AS400Exception, AS400SecurityException, InterruptedException, IOException { positionCursorToKeyLong(key, searchType, numberOfKeyFields); // Invalidate the cache if (cacheRecords_) { cache_.setIsEmpty(); } } /** *Positions the file cursor to the first record after the record specified *by key. The file must be open when invoking this method. *@param key The values which make up the key with which to find the record. *The key must contain at least one element. The types and order of *the elements that make up key must match the type and order of the *key fields in the record format for this object. Null values for key fields *are not supported. *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception ConnectionDroppedException If the connection is dropped unexpectedly. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ public void positionCursorAfter(Object[] key) throws AS400Exception, AS400SecurityException, InterruptedException, IOException { // Position the cursor to the record matching key positionCursorToKey(key, KeyedFile.TYPE_TABLE[KeyedFile.KEY_EQ]); if (cacheRecords_) { // Invalidate the cache. This will cause it to be refreshed // if we are caching and allow for cache access for any // subsequent (to this method's invocation) sequential // positioning or reading. cache_.setIsEmpty(); } positionCursorToNext(); } //@RBA public void positionCursorAfterLong(Object[] key) throws AS400Exception, AS400SecurityException, InterruptedException, IOException { // Position the cursor to the record matching key positionCursorToKeyLong(key, KeyedFile.TYPE_TABLE[KeyedFile.KEY_EQ]); if (cacheRecords_) { // Invalidate the cache. This will cause it to be refreshed // if we are caching and allow for cache access for any // subsequent (to this method's invocation) sequential // positioning or reading. cache_.setIsEmpty(); } positionCursorToNextLong(); } /** *Positions the file cursor to the first record after the record specified *by key. The file must be open when invoking this method. *@param key The byte array that contains the byte values which make up the key with which to find the record. *The byte array key must contain the byte values from at least one key field. The types and order of *the elements that make up key must match the type and order of the *key fields in the record format for this object. Null values for key fields *are not supported. *@param numberOfKeyFields The number of key fields contained in the byte array key. *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception ConnectionDroppedException If the connection is dropped unexpectedly. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ public void positionCursorAfter(byte[] key, int numberOfKeyFields) throws AS400Exception, AS400SecurityException, InterruptedException, IOException { // Position the cursor to the record matching key positionCursorToKey(key, KeyedFile.TYPE_TABLE[KeyedFile.KEY_EQ], numberOfKeyFields); if (cacheRecords_) { // Invalidate the cache. This will cause it to be refreshed // if we are caching and allow for cache access for any // subsequent (to this method's invocation) sequential // positioning or reading. cache_.setIsEmpty(); } positionCursorToNext(); } //@RBA public void positionCursorAfterLong(byte[] key, int numberOfKeyFields) throws AS400Exception, AS400SecurityException, InterruptedException, IOException { // Position the cursor to the record matching key positionCursorToKeyLong(key, KeyedFile.TYPE_TABLE[KeyedFile.KEY_EQ], numberOfKeyFields); if (cacheRecords_) { // Invalidate the cache. This will cause it to be refreshed // if we are caching and allow for cache access for any // subsequent (to this method's invocation) sequential // positioning or reading. cache_.setIsEmpty(); } positionCursorToNextLong(); } /** *Positions the file cursor to after the last record. *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ public abstract void positionCursorAfterLast() throws AS400Exception, AS400SecurityException, InterruptedException, IOException; /** *Positions the file cursor to the specified position (first, last, next, *previous). *@param type the type of position operation * @return array of records. *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ public abstract Record[] positionCursorAt(int type) throws AS400Exception, AS400SecurityException, InterruptedException, IOException; //@RBA public abstract Record[] positionCursorAtLong(int type) throws AS400Exception, AS400SecurityException, InterruptedException, IOException; /** *Positions the file cursor to the first record before the record specified *by the record number. The file must be open when invoking *this method. *@param recordNumber The record number of the record before which to position * the cursor. The recordNumber must be greater than zero. *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception ConnectionDroppedException If the connection is dropped unexpectedly. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ public void positionCursorBefore(int recordNumber) throws AS400Exception, AS400SecurityException, InterruptedException, IOException { if (cacheRecords_) { if (cache_.setPosition(recordNumber)) { if (!cache_.isBeginningOfCache()) { cache_.setPositionPrevious(); } else { // Record not in cache; position and refresh the cache positionCursorToIndex(recordNumber); positionCursorToPrevious(); } } else { // Not in cache; position and refresh the cache positionCursorToIndex(recordNumber); positionCursorToPrevious(); } } else { // Not caching positionCursorToIndex(recordNumber); positionCursorToPrevious(); } } /** *Positions the file cursor to the first record before the record specified *by key. The file must be open when invoking this method. *@param key The values which make up the key with which to find the record. *The key must contain at least one element. The types and order of *the elements that make up key must match the type and order of the *key fields in the record format for this object. Null values for key fields *are not supported. *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception ConnectionDroppedException If the connection is dropped unexpectedly. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ public void positionCursorBefore(Object[] key) throws AS400Exception, AS400SecurityException, InterruptedException, IOException { // Position the cursor to the record matching key positionCursorToKey(key, KeyedFile.TYPE_TABLE[KeyedFile.KEY_EQ]); if (cacheRecords_) { // Invalidate the cache. This will cause it to be refreshed // if we are caching and allow for cache access for any // subsequent (to this method's invocation) sequential // positioning or reading. cache_.setIsEmpty(); } try //@CRS { //@CRS // Call super's positionCursorToPrevious to get to the record // immediately following the matching record positionCursorToPrevious(); } //@CRS catch(AS400Exception e) //@CRS { //@CRS if (Trace.traceOn_) Trace.log(Trace.WARNING, "KeyedFile - Possible attempt to position by key before first record. Manually positioning cursor.", e); //@CRS if (e.getAS400Message().getID().equalsIgnoreCase("CPF5001")) //@CRS { //@CRS - Probably tried to position before first record. positionCursorBeforeFirst(); //@CRS } //@CRS else //@CRS { //@CRS throw e; //@CRS } //@CRS } //@CRS } //@RBA public void positionCursorBeforeLong(Object[] key) throws AS400Exception, AS400SecurityException, InterruptedException, IOException { // Position the cursor to the record matching key positionCursorToKeyLong(key, KeyedFile.TYPE_TABLE[KeyedFile.KEY_EQ]); if (cacheRecords_) { // Invalidate the cache. This will cause it to be refreshed // if we are caching and allow for cache access for any // subsequent (to this method's invocation) sequential // positioning or reading. cache_.setIsEmpty(); } try //@CRS { //@CRS // Call super's positionCursorToPrevious to get to the record // immediately following the matching record positionCursorToPreviousLong(); } //@CRS catch(AS400Exception e) //@CRS { //@CRS if (Trace.traceOn_) Trace.log(Trace.WARNING, "KeyedFile - Possible attempt to position by key before first record. Manually positioning cursor.", e); //@CRS if (e.getAS400Message().getID().equalsIgnoreCase("CPF5001")) //@CRS { //@CRS - Probably tried to position before first record. positionCursorBeforeFirst(); //@CRS } //@CRS else //@CRS { //@CRS throw e; //@CRS } //@CRS } //@CRS } /** *Positions the file cursor to the first record before the record specified *by key. The file must be open when invoking this method. *@param key The byte array that contains the byte values which make up the key with which to find the record. *The byte array key must contain the byte values from at least one key field. The types and order of *the elements that make up key must match the type and order of the *key fields in the record format for this object. Null values for key fields *are not supported. *@param numberOfKeyFields The number of key fields contained in the byte array key. *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception ConnectionDroppedException If the connection is dropped unexpectedly. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ public void positionCursorBefore(byte[] key, int numberOfKeyFields) throws AS400Exception, AS400SecurityException, InterruptedException, IOException { // Position the cursor to the record matching key positionCursorToKey(key, KeyedFile.TYPE_TABLE[KeyedFile.KEY_EQ], numberOfKeyFields); if (cacheRecords_) { // Invalidate the cache. This will cause it to be refreshed // if we are caching and allow for cache access for any // subsequent (to this method's invocation) sequential // positioning or reading. cache_.setIsEmpty(); } try //@CRS { //@CRS // Call super's positionCursorToPrevious to get to the record // immediately following the matching record positionCursorToPrevious(); } //@CRS catch(AS400Exception e) //@CRS { //@CRS if (Trace.traceOn_) Trace.log(Trace.WARNING, "KeyedFile - Possible attempt to position by key before first record. Manually positioning cursor.", e); //@CRS if (e.getAS400Message().getID().equalsIgnoreCase("CPF5001")) //@CRS { //@CRS - Probably tried to position before first record. positionCursorBeforeFirst(); //@CRS } //@CRS else //@CRS { //@CRS throw e; //@CRS } //@CRS } //@CRS } //@RBA public void positionCursorBeforeLong(byte[] key, int numberOfKeyFields) throws AS400Exception, AS400SecurityException, InterruptedException, IOException { // Position the cursor to the record matching key positionCursorToKeyLong(key, KeyedFile.TYPE_TABLE[KeyedFile.KEY_EQ], numberOfKeyFields); if (cacheRecords_) { // Invalidate the cache. This will cause it to be refreshed // if we are caching and allow for cache access for any // subsequent (to this method's invocation) sequential // positioning or reading. cache_.setIsEmpty(); } try //@CRS { //@CRS // Call super's positionCursorToPrevious to get to the record // immediately following the matching record positionCursorToPreviousLong(); } //@CRS catch(AS400Exception e) //@CRS { //@CRS if (Trace.traceOn_) Trace.log(Trace.WARNING, "KeyedFile - Possible attempt to position by key before first record. Manually positioning cursor.", e); //@CRS if (e.getAS400Message().getID().equalsIgnoreCase("CPF5001")) //@CRS { //@CRS - Probably tried to position before first record. positionCursorBeforeFirst(); //@CRS } //@CRS else //@CRS { //@CRS throw e; //@CRS } //@CRS } //@CRS } /** *Positions the file cursor to before the first record. *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ public abstract void positionCursorBeforeFirst() throws AS400Exception, AS400SecurityException, InterruptedException, IOException; /** *Positions the cursor to the first record. *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ public void positionCursorToFirst() throws AS400Exception, AS400SecurityException, InterruptedException, IOException { // If we are caching records and the cache contains the first record, // position the cache. Otherwise, position the file and refresh the // cache if we are caching records. if (cacheRecords_ && cache_.containsFirstRecord()) { cache_.setPositionFirst(); } else { if (cacheRecords_) { cache_.setIsEmpty(); } positionCursorAt(TYPE_GET_FIRST); } } //@RBA public void positionCursorToFirstLong() throws AS400Exception, AS400SecurityException, InterruptedException, IOException { // If we are caching records and the cache contains the first record, // position the cache. Otherwise, position the file and refresh the // cache if we are caching records. if (cacheRecords_ && cache_.containsFirstRecord()) { cache_.setPositionFirst(); } else { if (cacheRecords_) { cache_.setIsEmpty(); } positionCursorAtLong(TYPE_GET_FIRST); } } /** *Positions the cursor to the record at the specified file position. *@param index the file position *@return record at the specified file position *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ public abstract Record positionCursorToIndex(int index) throws AS400Exception, AS400SecurityException, InterruptedException, IOException; //@RBA public abstract Record positionCursorToIndexLong(long index) throws AS400Exception, AS400SecurityException, InterruptedException, IOException; /** *Positions the cursor to the first record in the file that matches the *specified key. *@param key the key *@param searchType the way to compare keys *@return Record after positioning *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ public abstract Record positionCursorToKey(Object[] key, int searchType) throws AS400Exception, AS400SecurityException, InterruptedException, IOException; //@RBA public abstract Record positionCursorToKeyLong(Object[] key, int searchType) throws AS400Exception, AS400SecurityException, InterruptedException, IOException; // @A2A /** *Positions the cursor to the first record in the file that matches the *specified key. *@param key the byte array that contains the byte values of the key *@param searchType the way to compare keys *@param numberOfKeyFields The number of key fields contained in the byte array key. * @return Record after positioning *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ public abstract Record positionCursorToKey(byte[] key, int searchType, int numberOfKeyFields) throws AS400Exception, AS400SecurityException, InterruptedException, IOException; public abstract Record positionCursorToKeyLong(byte[] key,//@RBA int searchType, int numberOfKeyFields) throws AS400Exception, AS400SecurityException, InterruptedException, IOException; /** *Positions the cursor to the last record in the file. *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ public void positionCursorToLast() throws AS400Exception, AS400SecurityException, InterruptedException, IOException { // If we are caching records and the cache contains the first record, // position the cache. Otherwise, position the file and refresh the // cache if we are caching records. if (cacheRecords_ && cache_.containsLastRecord()) { cache_.setPositionLast(); } else { if (cacheRecords_) { cache_.setIsEmpty(); } positionCursorAt(TYPE_GET_LAST); } } //@RBA public void positionCursorToLastLong() throws AS400Exception, AS400SecurityException, InterruptedException, IOException { // If we are caching records and the cache contains the first record, // position the cache. Otherwise, position the file and refresh the // cache if we are caching records. if (cacheRecords_ && cache_.containsLastRecord()) { cache_.setPositionLast(); } else { if (cacheRecords_) { cache_.setIsEmpty(); } positionCursorAtLong(TYPE_GET_LAST); } } /** *Positions the cursor to the next record in the file. *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ public void positionCursorToNext() throws AS400Exception, AS400SecurityException, InterruptedException, IOException { // Check if we are caching. If we are and we are not at the end of the cache, // just position ourselves within the cache, otherwise position ourselves in the file // and refresh the cache. if (cacheRecords_) { if (cache_.isEmpty() || (cache_.isEndOfCache() && cache_.currentDirection_ == DDMRecordCache.FORWARD)) { cache_.refresh(positionCursorAt(TYPE_GET_NEXT), DDMRecordCache.FORWARD, false, false); } else if (cache_.isEndOfCache() && cache_.currentDirection_ != DDMRecordCache.FORWARD) { refreshCache(null, DDMRecordCache.FORWARD, false, false); } else { if (Trace.isTraceOn()) { Trace.log(Trace.INFORMATION, "positionCursorToNext: positioning in cache."); } cache_.setPositionNext(); } } else { // Not caching; just position ourselves in the file positionCursorAt(TYPE_GET_NEXT); } } //@RBA public void positionCursorToNextLong() throws AS400Exception, AS400SecurityException, InterruptedException, IOException { // Check if we are caching. If we are and we are not at the end of the cache, // just position ourselves within the cache, otherwise position ourselves in the file // and refresh the cache. if (cacheRecords_) { if (cache_.isEmpty() || (cache_.isEndOfCache() && cache_.currentDirection_ == DDMRecordCache.FORWARD)) { cache_.refresh(positionCursorAtLong(TYPE_GET_NEXT), DDMRecordCache.FORWARD, false, false); } else if (cache_.isEndOfCache() && cache_.currentDirection_ != DDMRecordCache.FORWARD) { refreshCacheLong(null, DDMRecordCache.FORWARD, false, false); } else { if (Trace.isTraceOn()) { Trace.log(Trace.INFORMATION, "positionCursorToNext: positioning in cache."); } cache_.setPositionNext(); } } else { // Not caching; just position ourselves in the file positionCursorAtLong(TYPE_GET_NEXT); } } /** *Positions the cursor to the previous record in the file. *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ public void positionCursorToPrevious() throws AS400Exception, AS400SecurityException, InterruptedException, IOException { // Check if we are caching. If we are and we are not at the end of the cache, // just position ourselves within the cache, otherwise position ourselves in the file // and refresh the cache. if (cacheRecords_) { if (cache_.isEmpty() || (cache_.isBeginningOfCache() && cache_.currentDirection_ == DDMRecordCache.BACKWARD)) { cache_.refresh(positionCursorAt(TYPE_GET_PREV), DDMRecordCache.BACKWARD, false, false); } else if (cache_.isBeginningOfCache() && cache_.currentDirection_ != DDMRecordCache.BACKWARD) { refreshCache(null, DDMRecordCache.BACKWARD, false, false); } else { if (Trace.isTraceOn()) { Trace.log(Trace.INFORMATION, "positionCursorToPrev: positioning in cache."); } cache_.setPositionPrevious(); } } else { // Not caching; just position ourselves in the file positionCursorAt(TYPE_GET_PREV); } } //@RBA public void positionCursorToPreviousLong() throws AS400Exception, AS400SecurityException, InterruptedException, IOException { // Check if we are caching. If we are and we are not at the end of the cache, // just position ourselves within the cache, otherwise position ourselves in the file // and refresh the cache. if (cacheRecords_) { if (cache_.isEmpty() || (cache_.isBeginningOfCache() && cache_.currentDirection_ == DDMRecordCache.BACKWARD)) { cache_.refresh(positionCursorAt(TYPE_GET_PREV), DDMRecordCache.BACKWARD, false, false); } else if (cache_.isBeginningOfCache() && cache_.currentDirection_ != DDMRecordCache.BACKWARD) { refreshCacheLong(null, DDMRecordCache.BACKWARD, false, false); } else { if (Trace.isTraceOn()) { Trace.log(Trace.INFORMATION, "positionCursorToPrev: positioning in cache."); } cache_.setPositionPrevious(); } } else { // Not caching; just position ourselves in the file positionCursorAtLong(TYPE_GET_PREV); } } /** Reads the record at the current file position. @return the record read. *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ public Record read() throws AS400Exception, AS400SecurityException, InterruptedException, IOException { // If we are caching, get the current record at which we are pointing. If we are // not positioned on record in the cache we are not positioned on a record in the // file either. In order to get the correct error information thrown, we call // readRecord() to read from the file and throw the exception. Record r = null; if (cacheRecords_) { r = cache_.getCurrent(); } if (r == null) { r = readRecord(TYPE_GET_SAME); } return r; } //@RBA public Record readLong() throws AS400Exception, AS400SecurityException, InterruptedException, IOException { // If we are caching, get the current record at which we are pointing. If we are // not positioned on record in the cache we are not positioned on a record in the // file either. In order to get the correct error information thrown, we call // readRecord() to read from the file and throw the exception. Record r = null; if (cacheRecords_) { r = cache_.getCurrent(); } if (r == null) { r = readRecordLong(TYPE_GET_SAME); } return r; } /** Reads the record at the specified file position. @param recordNumber the file position @return the record read. *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ public Record read(int recordNumber) //@B0C -- this is overridden in the subclasses throws AS400Exception, AS400SecurityException, InterruptedException, IOException { //@B0D if (cacheRecords_) //@B0D { Record r = cache_.getRecord(recordNumber); if (r == null) { // Record is not in cache; read it from the file and refresh try { // Position to the record and refresh the cache r = positionCursorToIndex(recordNumber); refreshCache(null, DDMRecordCache.FORWARD, false, false); // Add the current record to the cache at the beginning cache_.add(r, false); cache_.setPositionFirst(); } catch (AS400Exception e) { // If we get CPF5001 or CPF5006 (end of file or record not found) // from the position operation we want to return null in order // to mimic what we do when we are not caching. String id = e.getAS400Message().getID(); if (id.equals("CPF5001") || id.equals("CPF5006")) { return null; } else { throw e; } } } return r; //@B0D } //@B0D else //@B0D { //@B0D return read(recordNumber); //@B0D } } /** *Reads the first record with the specified key based on the specified search type. *@param key The values that make up the key with which to find the record. *@param searchType The type of read. This value is one of the TYPE_GETKEY_* constants. *@return The record read. *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ public abstract Record read(Object[] key, int searchType) throws AS400Exception, AS400SecurityException, InterruptedException, IOException; //@RBA public abstract Record readLong(Object[] key, int searchType) throws AS400Exception, AS400SecurityException, InterruptedException, IOException; // @A2A /** *Reads the first record with the specified key based on the specified search type. *@param key The byte array that contains the byte values that make up the key with which to find the record. *@param searchType The type of read. This value is one of the TYPE_GETKEY_* constants. *@param numberOfKeyFields The number of key fields contained in the byte array key. *@return The record read. *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ public abstract Record read(byte[] key, int searchType, int numberOfKeyFields) throws AS400Exception, AS400SecurityException, InterruptedException, IOException; //@RBA public abstract Record readLong(byte[] key, int searchType, int numberOfKeyFields) throws AS400Exception, AS400SecurityException, InterruptedException, IOException; /* Record read2(byte[] key, int searchType, int numberOfKeyFields) throws AS400Exception, AS400SecurityException, InterruptedException, IOException { // Determine the type of get Record r = read(key, KeyedFile.TYPE_TABLE[searchType], numberOfKeyFields); if (cacheRecords_) { cache_.setIsEmpty(); } return r; } */ /** *Reads the first record after the record with the specified record number. *The file must be open when invoking this method. *@param recordNumber record number of the record prior to the record to be read. *The recordNumber must be greater than zero. *@return The record read. If the record is not found, null is returned. *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception ConnectionDroppedException If the connection is dropped unexpectedly. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ public Record readAfter(int recordNumber) throws AS400Exception, AS400SecurityException, InterruptedException, IOException { if (cacheRecords_) { // Check for record in the cache if (cache_.setPosition(recordNumber)) { // Record recordNumber is here; are we at the end of the cache? if (!cache_.isEndOfCache()) { // Next record in cache is the one we want return cache_.getNext(); } else { // We need to go to the file to get the record // Don't need to bother to invalidate the cache as we are at // the end of the cache and readNext will check that // and refresh. positionCursorToIndex(recordNumber); return readNext(); } } else { // We need to go to the file to get the record // Invalidate the cache. cache_.setIsEmpty(); positionCursorToIndex(recordNumber); return readNext(); } } else { // Position the cursor and call super's readNext() positionCursorToIndex(recordNumber); return readNext(); } } /** *Reads the first record after the record with the specified key. The file must *be open when invoking this method. *@param key The values that make up the key with which to find the record. *The key must contain at least one element. The types and order of *the elements that make up key must match the type and order of the *key fields in the record format for this object. Null values for key fields *are not supported. *@return The record read. If the record is not found, null is returned. *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception ConnectionDroppedException If the connection is dropped unexpectedly. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ public Record readAfter(Object[] key) throws AS400Exception, AS400SecurityException, InterruptedException, IOException { positionCursorToKey(key, KeyedFile.TYPE_TABLE[KeyedFile.KEY_EQ]); if (cacheRecords_) { cache_.setIsEmpty(); } return readNext(); } //@RBA public Record readAfterLong(Object[] key) throws AS400Exception, AS400SecurityException, InterruptedException, IOException { positionCursorToKeyLong(key, KeyedFile.TYPE_TABLE[KeyedFile.KEY_EQ]); if (cacheRecords_) { cache_.setIsEmpty(); } return readNextLong(); } /** *Reads the first record after the record with the specified key. The file must *be open when invoking this method. *@param key The byte array that contains the byte values that make up the key with which to find the record. *The byte array key must contain the byte values from at least one key field. The types and order of *the elements that make up key must match the type and order of the *key fields in the record format for this object. Null values for key fields *are not supported. *@param numberOfKeyFields The number of key fields contained in the byte array key. *@return The record read. If the record is not found, null is returned. *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception ConnectionDroppedException If the connection is dropped unexpectedly. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ public Record readAfter(byte[] key, int numberOfKeyFields) throws AS400Exception, AS400SecurityException, InterruptedException, IOException { positionCursorToKey(key, KeyedFile.TYPE_TABLE[KeyedFile.KEY_EQ], numberOfKeyFields); if (cacheRecords_) { cache_.setIsEmpty(); } return readNext(); } //@RBA public Record readAfterLong(byte[] key, int numberOfKeyFields) throws AS400Exception, AS400SecurityException, InterruptedException, IOException { positionCursorToKeyLong(key, KeyedFile.TYPE_TABLE[KeyedFile.KEY_EQ], numberOfKeyFields); if (cacheRecords_) { cache_.setIsEmpty(); } return readNextLong(); } /** *Reads all the records in the file. *@param fileType The type of file. Valid values are: key or seq * @param bf *@return The records read. *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ public abstract Record[] readAll(String fileType, int bf) //@D0C throws AS400Exception, AS400SecurityException, InterruptedException, IOException; //@RBA public abstract Record[] readAllLong(String fileType, int bf) throws AS400Exception, AS400SecurityException, InterruptedException, IOException; /** *Reads the first record before the record with the specified record number. *The file must be open when invoking this method. *@param recordNumber The record number of the record after the record to be read. *The recordNumber must be greater than zero. *@return The record read. If the record is not found, null is returned. *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception ConnectionDroppedException If the connection is dropped unexpectedly. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ public Record readBefore(int recordNumber) throws AS400Exception, AS400SecurityException, InterruptedException, IOException { if (cacheRecords_) { // Check for record in the cache if (cache_.setPosition(recordNumber)) { // Record recordNumber is here; are we at the beginning of the cache? if (!cache_.isBeginningOfCache()) { // Next record in cache is the one we want return cache_.getPrevious(); } else { // We need to go to the file to get the record // Don't need to bother to invalidate the cache as we are at // the beginning of the cache and readPrevious will check that // and refresh. positionCursorToIndex(recordNumber); return readPrevious(); } } else { // We need to go to the file to get the record // Invalidate the cache. cache_.setIsEmpty(); positionCursorToIndex(recordNumber); return readPrevious(); } } else { // Position the cursor and call super's readPrevious() positionCursorToIndex(recordNumber); return readPrevious(); } } /** *Reads the first record before the record with the specified key. The file must *be open when invoking this method. *@param key The values that make up the key with which to find the record. *The key must contain at least one element. The types and order of *the elements that make up key must match the type and order of the *key fields in the record format for this object. Null values for key fields *are not supported. *@return The record read. If the record is not found, null is returned. *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception ConnectionDroppedException If the connection is dropped unexpectedly. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ public Record readBefore(Object[] key) throws AS400Exception, AS400SecurityException, InterruptedException, IOException { positionCursorToKey(key, KeyedFile.TYPE_TABLE[KeyedFile.KEY_EQ]); if (cacheRecords_) { cache_.setIsEmpty(); } return readPrevious(); } //@RBA public Record readBeforeLong(Object[] key) throws AS400Exception, AS400SecurityException, InterruptedException, IOException { positionCursorToKeyLong(key, KeyedFile.TYPE_TABLE[KeyedFile.KEY_EQ]); if (cacheRecords_) { cache_.setIsEmpty(); } return readPreviousLong(); } /** *Reads the first record before the record with the specified key. The file must *be open when invoking this method. *@param key The byte array that contains the byte values that make up the key with which to find the record. *The byte array key must contain the byte values from at least one key field. The types and order of *the elements that make up key must match the type and order of the *key fields in the record format for this object. Null values for key fields *are not supported. *@param numberOfKeyFields The number of key fields contained in the byte array key. *@return The record read. If the record is not found, null is returned. *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception ConnectionDroppedException If the connection is dropped unexpectedly. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ public Record readBefore(byte[] key, int numberOfKeyFields) throws AS400Exception, AS400SecurityException, InterruptedException, IOException { positionCursorToKey(key, KeyedFile.TYPE_TABLE[KeyedFile.KEY_EQ], numberOfKeyFields); if (cacheRecords_) { cache_.setIsEmpty(); } return readPrevious(); } //@RBA public Record readBeforeLong(byte[] key, int numberOfKeyFields) throws AS400Exception, AS400SecurityException, InterruptedException, IOException { positionCursorToKeyLong(key, KeyedFile.TYPE_TABLE[KeyedFile.KEY_EQ], numberOfKeyFields); if (cacheRecords_) { cache_.setIsEmpty(); } return readPreviousLong(); } /** *Reads the first record from the file. *@return the first record. *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ public Record readFirst() throws AS400Exception, AS400SecurityException, InterruptedException, IOException { // If we are caching, check the cache for the record. IF not found refresh the // cache. if (cacheRecords_) { if (cache_.containsFirstRecord()) { return cache_.getFirst(); } else //@A4A: Invalidate the cache since we will be going to the system { // Invalidate the cache cache_.setIsEmpty(); } } // Not caching, read from the file. return readRecord(TYPE_GET_FIRST); } /** *Reads the last record from the file. *@return the first record. *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ public Record readLast() throws AS400Exception, AS400SecurityException, InterruptedException, IOException { // If we are caching, check the cache for the record. IF not found refresh the // cache. if (cacheRecords_) { if (cache_.containsLastRecord()) { return cache_.getLast(); } else //@A4A: Invalidate the cache since we will be going to the system { // Invalidate the cache cache_.setIsEmpty(); } } // Not caching, read from the file. return readRecord(TYPE_GET_LAST); } //@RBA public Record readLastLong() throws AS400Exception, AS400SecurityException, InterruptedException, IOException { // If we are caching, check the cache for the record. IF not found refresh the // cache. if (cacheRecords_) { if (cache_.containsLastRecord()) { return cache_.getLast(); } else //@A4A: Invalidate the cache since we will be going to the system { // Invalidate the cache cache_.setIsEmpty(); } } // Not caching, read from the file. return readRecordLong(TYPE_GET_LAST); } /** *Reads the next record from the file. *@return the first record. *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ public Record readNext() throws AS400Exception, AS400SecurityException, InterruptedException, IOException { Record r = null; // If we are caching, check the cache for the record. IF not found refresh the // cache. if (cacheRecords_) { r = cache_.getNext(); if (r == null) { if (Trace.isTraceOn()) { Trace.log(Trace.INFORMATION, "AS400FileImplBase.readNext(): cache_.getNext() returned null."); } refreshCache(null, DDMRecordCache.FORWARD, false, false); return cache_.getCurrent(); } else { return r; } } // Not caching, read from the file. return readRecord(TYPE_GET_NEXT); } //@RBA public Record readNextLong() throws AS400Exception, AS400SecurityException, InterruptedException, IOException { Record r = null; // If we are caching, check the cache for the record. IF not found refresh the // cache. if (cacheRecords_) { r = cache_.getNext(); if (r == null) { if (Trace.isTraceOn()) { Trace.log(Trace.INFORMATION, "AS400FileImplBase.readNext(): cache_.getNext() returned null."); } refreshCacheLong(null, DDMRecordCache.FORWARD, false, false); return cache_.getCurrent(); } else { return r; } } // Not caching, read from the file. return readRecordLong(TYPE_GET_NEXT); } /** *Reads the next record whose key matches the full key of the current record. *The file must be open when invoking this method. The file must be *positioned on an active record when invoking this method. *@return The record read. If the record is not found, null is returned. *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception ConnectionDroppedException If the connection is dropped unexpectedly. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ public Record readNextEqual() throws AS400Exception, AS400SecurityException, InterruptedException, IOException { Object[] key; if (cacheRecords_) { if (!cache_.isEmpty()) { Record r = null; Record current = cache_.getCurrent(); if (current != null) { key = current.getKeyFields(); try { //@B4C - when reading, get out early by checking comparison r = readNext(); int match = UNKNOWN; if (r != null) match = compareKeys(key, r.getKeyFields()); while (r != null && (match == GREATER_THAN || match == UNKNOWN)) { r = readNext(); if (r != null) match = compareKeys(key, r.getKeyFields()); } if (match != EQUAL) r = null; //@B4C - end change } catch (AS400Exception e) { if (e.getAS400Message().getID().equals("CPF5025")) { return null; } else { throw e; } } return r; } } } key = recordFormat_.getNewRecord().getKeyFields(); return read(key, 0x0E); } //@RBA public Record readNextEqualLong() throws AS400Exception, AS400SecurityException, InterruptedException, IOException { Object[] key; if (cacheRecords_) { if (!cache_.isEmpty()) { Record r = null; Record current = cache_.getCurrent(); if (current != null) { key = current.getKeyFields(); try { //@B4C - when reading, get out early by checking comparison r = readNextLong(); int match = UNKNOWN; if (r != null) match = compareKeys(key, r.getKeyFields()); while (r != null && (match == GREATER_THAN || match == UNKNOWN)) { r = readNextLong(); if (r != null) match = compareKeys(key, r.getKeyFields()); } if (match != EQUAL) r = null; //@B4C - end change } catch (AS400Exception e) { if (e.getAS400Message().getID().equals("CPF5025")) { return null; } else { throw e; } } return r; } } } key = recordFormat_.getNewRecord().getKeyFields(); return readLong(key, 0x0E); } /** *Reads the next record whose key matches the specified key. The search does *not include the current record. The key may be a partial key. *The file must be open when invoking this method. * @param key *@return The record read. If the record is not found, null is returned. *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception ConnectionDroppedException If the connection is dropped unexpectedly. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ public Record readNextEqual(Object[] key) throws AS400Exception, AS400SecurityException, InterruptedException, IOException { Record r = null; try { //@B4C - when reading, get out early by checking comparison r = readNext(); int match = UNKNOWN; if (r != null) match = compareKeys(key, r.getKeyFields()); while (r != null && (match == GREATER_THAN || match == UNKNOWN)) { r = readNext(); if (r != null) match = compareKeys(key, r.getKeyFields()); } if (match != EQUAL) r = null; //@B4C - end change } catch (AS400Exception e) { if (e.getAS400Message().getID().equals("CPF5025")) { return null; } else { throw e; } } return r; } //@RBA public Record readNextEqualLong(Object[] key) throws AS400Exception, AS400SecurityException, InterruptedException, IOException { Record r = null; try { //@B4C - when reading, get out early by checking comparison r = readNextLong(); int match = UNKNOWN; if (r != null) match = compareKeys(key, r.getKeyFields()); while (r != null && (match == GREATER_THAN || match == UNKNOWN)) { r = readNextLong(); if (r != null) match = compareKeys(key, r.getKeyFields()); } if (match != EQUAL) r = null; //@B4C - end change } catch (AS400Exception e) { if (e.getAS400Message().getID().equals("CPF5025")) { return null; } else { throw e; } } return r; } /** *Reads the next record whose key matches the specified key. The search does *not include the current record. The key may be a partial key. *The file must be open when invoking this method. *@param key The byte array that contains the byte values that make up the key with which to find the record. *The byte array key must contain the byte values from at least one key field. The types and order of *the elements that make up key must match the type and order of the *key fields in the record format for this object. Null values for key fields *are not supported. *@param numberOfKeyFields The number of key fields contained in the byte array key. *@return The record read. If the record is not found, null is returned. *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception ConnectionDroppedException If the connection is dropped unexpectedly. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ public Record readNextEqual(byte[] key, int numberOfKeyFields) throws AS400Exception, AS400SecurityException, InterruptedException, IOException { Record r = null; try { //@B4C - when reading, get out early by checking comparison r = readNext(); int match = UNKNOWN; if (r != null) match = compareKeys(key, r.getKeyFieldsAsBytes(), numberOfKeyFields); while (r != null && (match == GREATER_THAN || match == UNKNOWN)) { r = readNext(); if (r != null) match = compareKeys(key, r.getKeyFieldsAsBytes(), numberOfKeyFields); } if (match != EQUAL) r = null; //@B4C - end change } catch (AS400Exception e) { if (e.getAS400Message().getID().equals("CPF5025")) { return null; } else { throw e; } } return r; } //@RBA public Record readNextEqualLong(byte[] key, int numberOfKeyFields) throws AS400Exception, AS400SecurityException, InterruptedException, IOException { Record r = null; try { //@B4C - when reading, get out early by checking comparison r = readNextLong(); int match = UNKNOWN; if (r != null) match = compareKeys(key, r.getKeyFieldsAsBytes(), numberOfKeyFields); while (r != null && (match == GREATER_THAN || match == UNKNOWN)) { r = readNextLong(); if (r != null) match = compareKeys(key, r.getKeyFieldsAsBytes(), numberOfKeyFields); } if (match != EQUAL) r = null; //@B4C - end change } catch (AS400Exception e) { if (e.getAS400Message().getID().equals("CPF5025")) { return null; } else { throw e; } } return r; } /** *Reads the previous record from the file. *@return the first record. *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ public Record readPrevious() throws AS400Exception, AS400SecurityException, InterruptedException, IOException { // If we are caching, check the cache for the record. IF not found refresh the // cache. Record r = null; if (cacheRecords_) { r = cache_.getPrevious(); if (r == null) { if (Trace.isTraceOn()) { Trace.log(Trace.INFORMATION, "AS400FileImplBase.readPrevious(): cache returned null."); } refreshCache(null, DDMRecordCache.BACKWARD, false, false); return cache_.getCurrent(); } else { return r; } } // Not caching, read from the file. return readRecord(TYPE_GET_PREV); } //@RBA public Record readPreviousLong() throws AS400Exception, AS400SecurityException, InterruptedException, IOException { // If we are caching, check the cache for the record. IF not found refresh the // cache. Record r = null; if (cacheRecords_) { r = cache_.getPrevious(); if (r == null) { if (Trace.isTraceOn()) { Trace.log(Trace.INFORMATION, "AS400FileImplBase.readPrevious(): cache returned null."); } refreshCacheLong(null, DDMRecordCache.BACKWARD, false, false); return cache_.getCurrent(); } else { return r; } } // Not caching, read from the file. return readRecordLong(TYPE_GET_PREV); } /** *Reads the previous record whose key matches the key of the current record. * The file must be open when invoking this method. The file must be *positioned on an active record when invoking this method. *@return The record read. If the record is not found, null is returned. *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception ConnectionDroppedException If the connection is dropped unexpectedly. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ public Record readPreviousEqual() throws AS400Exception, AS400SecurityException, InterruptedException, IOException { Object[] key; Record r; if (cacheRecords_) { if (!cache_.isEmpty()) { Record current = cache_.getCurrent(); if (current != null) { key = current.getKeyFields(); try { //@B4C - when reading, get out early by checking comparison r = readPrevious(); int match = UNKNOWN; if (r != null) match = compareKeys(key, r.getKeyFields()); while (r != null && (match == LESS_THAN || match == UNKNOWN)) { r = readPrevious(); if (r != null) match = compareKeys(key, r.getKeyFields()); } if (match != EQUAL) r = null; //@B4C - end change } catch (AS400Exception e) { if (e.getAS400Message().getID().equals("CPF5025")) { return null; } else { throw e; } } return r; } } } key = recordFormat_.getNewRecord().getKeyFields(); return read(key, 0x0F); } //@RBA public Record readPreviousEqualLong() throws AS400Exception, AS400SecurityException, InterruptedException, IOException { Object[] key; Record r; if (cacheRecords_) { if (!cache_.isEmpty()) { Record current = cache_.getCurrent(); if (current != null) { key = current.getKeyFields(); try { //@B4C - when reading, get out early by checking comparison r = readPreviousLong(); int match = UNKNOWN; if (r != null) match = compareKeys(key, r.getKeyFields()); while (r != null && (match == LESS_THAN || match == UNKNOWN)) { r = readPreviousLong(); if (r != null) match = compareKeys(key, r.getKeyFields()); } if (match != EQUAL) r = null; //@B4C - end change } catch (AS400Exception e) { if (e.getAS400Message().getID().equals("CPF5025")) { return null; } else { throw e; } } return r; } } } key = recordFormat_.getNewRecord().getKeyFields(); return readLong(key, 0x0F); } /** *Reads the previous record whose key matches the specified key. The search does *not include the current record. The key may be a partial key. *The file must be open when invoking this method. * @param key *@return The record read. If the record is not found, null is returned. *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception ConnectionDroppedException If the connection is dropped unexpectedly. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ public Record readPreviousEqual(Object[] key) throws AS400Exception, AS400SecurityException, InterruptedException, IOException { Record r = null; try { //@B4C - when reading, get out early by checking comparison r = readPrevious(); int match = UNKNOWN; if (r != null) match = compareKeys(key, r.getKeyFields()); while (r != null && (match == LESS_THAN || match == UNKNOWN)) { r = readPrevious(); if (r != null) match = compareKeys(key, r.getKeyFields()); } if (match != EQUAL) r = null; //@B4C - end change } catch (AS400Exception e) { if (e.getAS400Message().getID().equals("CPF5025")) { return null; } else { throw e; } } return r; } //@RBA public Record readPreviousEqualLong(Object[] key) throws AS400Exception, AS400SecurityException, InterruptedException, IOException { Record r = null; try { //@B4C - when reading, get out early by checking comparison r = readPreviousLong(); int match = UNKNOWN; if (r != null) match = compareKeys(key, r.getKeyFields()); while (r != null && (match == LESS_THAN || match == UNKNOWN)) { r = readPreviousLong(); if (r != null) match = compareKeys(key, r.getKeyFields()); } if (match != EQUAL) r = null; //@B4C - end change } catch (AS400Exception e) { if (e.getAS400Message().getID().equals("CPF5025")) { return null; } else { throw e; } } return r; } /** *Reads the previous record whose key matches the specified key. The search does *not include the current record. The key may be a partial key. *The file must be open when invoking this method. *@param key The byte array that contains the byte values that make up the key with which to find the record. *The byte array key must contain the byte values from at least one key field. The types and order of *the elements that make up key must match the type and order of the *key fields in the record format for this object. Null values for key fields *are not supported. *@param numberOfKeyFields The number of key fields contained in the byte array key. *@return The record read. If the record is not found, null is returned. *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception ConnectionDroppedException If the connection is dropped unexpectedly. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ public Record readPreviousEqual(byte[] key, int numberOfKeyFields) throws AS400Exception, AS400SecurityException, InterruptedException, IOException { Record r = null; try { //@B4C - when reading, get out early by checking comparison r = readPrevious(); int match = UNKNOWN; if (r != null) match = compareKeys(key, r.getKeyFieldsAsBytes(), numberOfKeyFields); while (r != null && (match == LESS_THAN || match == UNKNOWN)) { r = readPrevious(); if (r != null) match = compareKeys(key, r.getKeyFieldsAsBytes(), numberOfKeyFields); } if (match != EQUAL) r = null; //@B4C - end change } catch (AS400Exception e) { if (e.getAS400Message().getID().equals("CPF5025")) { return null; } else { throw e; } } return r; } //@RBA public Record readPreviousEqualLong(byte[] key, int numberOfKeyFields) throws AS400Exception, AS400SecurityException, InterruptedException, IOException { Record r = null; try { //@B4C - when reading, get out early by checking comparison r = readPreviousLong(); int match = UNKNOWN; if (r != null) match = compareKeys(key, r.getKeyFieldsAsBytes(), numberOfKeyFields); while (r != null && (match == LESS_THAN || match == UNKNOWN)) { r = readPreviousLong(); if (r != null) match = compareKeys(key, r.getKeyFieldsAsBytes(), numberOfKeyFields); } if (match != EQUAL) r = null; //@B4C - end change } catch (AS400Exception e) { if (e.getAS400Message().getID().equals("CPF5025")) { return null; } else { throw e; } } return r; } /** Reads the record at the current file position. *@param type type of read (first, last, next, previous) @return the record read. *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ public abstract Record readRecord(int type) throws AS400Exception, AS400SecurityException, InterruptedException, IOException; //@RBA public abstract Record readRecordLong(int type) throws AS400Exception, AS400SecurityException, InterruptedException, IOException; /** *Reads records from the file. The next or previous 'blockingFactor_' *records are retrieved depending on the direction specified. *@param direction (DDMRecordCache.FORWARD or DDMRecordCache.BACKWARD) *@return the records read *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ public abstract Record[] readRecords(int direction) throws AS400Exception, AS400SecurityException, InterruptedException, IOException; //@RBA public abstract Record[] readRecordsLong(int direction) throws AS400Exception, AS400SecurityException, InterruptedException, IOException; /** *Refreshes the record cache for this file object. Depending on the direction *specified, a readNext() (direction = FORWARD) or readPrevious() *(direction = BACKWARD) will be specified on the S38GETM (get multiple records). *@param records The records with which to refresh the cache. If records *is null, the records will be retrieved via impl.readRecords(). *@param direction The direction in which to search the cache for records. *@param containsFirstRecord Indicates if the first record will be contained in the *cache after the getm. *@param containsLastRecord Indicates if the last record will be contained in the *cache after the getm. *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception ConnectionDroppedException If the connection is dropped unexpectedly. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ //@RBA public void refreshCacheLong(Record[] records, int direction, boolean containsFirstRecord, boolean containsLastRecord) throws AS400Exception, AS400SecurityException, InterruptedException, IOException { // Fill the cache. If null was returned, the cache will set itself to empty. if (Trace.isTraceOn()) { Trace.log(Trace.INFORMATION, "AS400FileImplBase.refreshCache: refreshing cache," + String.valueOf(direction)); } Record r = null; if ((cache_.currentDirection_ == direction || cache_.isEmpty())) { // Invalidate the cache in case an exception occurs cache_.setIsEmpty(); // We refresh if we are going in the same direction if (records == null) { // Read records. We don't need to create the implementation because // this method is only called by code that ensures that this object is // already open. records = readRecordsLong(direction); } if (Trace.isTraceOn()) { Trace.log(Trace.INFORMATION, "AS400FileImplBase.refreshCache(): cursors in synch."); } cache_.refresh(records, direction, containsFirstRecord, containsLastRecord); } else { // The host cursor and cache cursor are out of synch - need to re-synch // If we are a SequentialFile, we will simply position by record number of // the record we are currently at in the cache to correctly position // ourselves. If we are a KeyedFile, we need to position by key to // the record whose key matched the key of the record we are currently // at in the cache. Then we compare the record number. This is in case // the file has duplicate keys. If the record number does not match, // we do a readNext() and compare, etc. //@G0: Always position by record number. // The code path for positioning by key was causing a performance hit // and seems to be superfluous. long recordNumber = (cache_.getCurrent() == null)? cache_.getNext().getRecordNumberLong() : cache_.getCurrent().getRecordNumberLong(); if (Trace.isTraceOn()) { Trace.log(Trace.INFORMATION, "AS400FileImplBase.refreshCache(): cursors not in synch."); } //@G0D if (!isKeyed_) //@B0C: Must be instance of SequentialFile //@G0D { // Invalidate the cache in case an exception occurs cache_.setIsEmpty(); positionCursorLong(recordNumber); /*@G0D } else { Object[] key = (cache_.getCurrent() == null)? cache_.getNext().getKeyFields() : cache_.getCurrent().getKeyFields(); r = read(key, KeyedFile.TYPE_TABLE[KeyedFile.KEY_EQ]); //@B0C // Turn of caching so that we can position in the file cacheRecords_ = false; // Invalidte the cache in the event of an exception cache_.setIsEmpty(); while (r != null && r.getRecordNumber() != recordNumber) { try { r = readNextEqual(); } catch(AS400Exception e) { cacheRecords_ = true; throw e; } catch(AS400SecurityException e) { cacheRecords_ = true; throw e; } catch(IOException e) { cacheRecords_ = true; throw e; } catch(InterruptedException e) { cacheRecords_ = true; throw e; } } cacheRecords_ = true; } */ //@G0D if (records == null) { // Read records. We don't need to create the implementation because // this method is only called by code that ensures that this object is // already open. records = readRecordsLong(direction); } // Now we can refresh the cache cache_.refresh(records, direction, containsFirstRecord, containsLastRecord); } } public void refreshCache(Record[] records, int direction, boolean containsFirstRecord, boolean containsLastRecord) throws AS400Exception, AS400SecurityException, InterruptedException, IOException { // Fill the cache. If null was returned, the cache will set itself to empty. if (Trace.isTraceOn()) { Trace.log(Trace.INFORMATION, "AS400FileImplBase.refreshCache: refreshing cache," + String.valueOf(direction)); } Record r = null; if ((cache_.currentDirection_ == direction || cache_.isEmpty())) { // Invalidate the cache in case an exception occurs cache_.setIsEmpty(); // We refresh if we are going in the same direction if (records == null) { // Read records. We don't need to create the implementation because // this method is only called by code that ensures that this object is // already open. records = readRecords(direction); } if (Trace.isTraceOn()) { Trace.log(Trace.INFORMATION, "AS400FileImplBase.refreshCache(): cursors in synch."); } cache_.refresh(records, direction, containsFirstRecord, containsLastRecord); } else { // The host cursor and cache cursor are out of synch - need to re-synch // If we are a SequentialFile, we will simply position by record number of // the record we are currently at in the cache to correctly position // ourselves. If we are a KeyedFile, we need to position by key to // the record whose key matched the key of the record we are currently // at in the cache. Then we compare the record number. This is in case // the file has duplicate keys. If the record number does not match, // we do a readNext() and compare, etc. //@G0: Always position by record number. // The code path for positioning by key was causing a performance hit // and seems to be superfluous. int recordNumber = (cache_.getCurrent() == null)? cache_.getNext().getRecordNumber() : cache_.getCurrent().getRecordNumber(); if (Trace.isTraceOn()) { Trace.log(Trace.INFORMATION, "AS400FileImplBase.refreshCache(): cursors not in synch."); } //@G0D if (!isKeyed_) //@B0C: Must be instance of SequentialFile //@G0D { // Invalidate the cache in case an exception occurs cache_.setIsEmpty(); positionCursor(recordNumber); /*@G0D } else { Object[] key = (cache_.getCurrent() == null)? cache_.getNext().getKeyFields() : cache_.getCurrent().getKeyFields(); r = read(key, KeyedFile.TYPE_TABLE[KeyedFile.KEY_EQ]); //@B0C // Turn of caching so that we can position in the file cacheRecords_ = false; // Invalidte the cache in the event of an exception cache_.setIsEmpty(); while (r != null && r.getRecordNumber() != recordNumber) { try { r = readNextEqual(); } catch(AS400Exception e) { cacheRecords_ = true; throw e; } catch(AS400SecurityException e) { cacheRecords_ = true; throw e; } catch(IOException e) { cacheRecords_ = true; throw e; } catch(InterruptedException e) { cacheRecords_ = true; throw e; } } cacheRecords_ = true; } */ //@G0D if (records == null) { // Read records. We don't need to create the implementation because // this method is only called by code that ensures that this object is // already open. records = readRecords(direction); } // Now we can refresh the cache cache_.refresh(records, direction, containsFirstRecord, containsLastRecord); } } /** *Refreshes the record cache for this file. Invoking this method will cause the *retrieval of records from the server. The cursor position is set to the *first record of the file. This method only needs to *be invoked if a blocking factor greater than 1 is being used, and the user *wants to refresh the records in the cache. The file must be open when invoking *this method. No action is taken if records are not being cached (for example, the *blocking factor is set to one). *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception ConnectionDroppedException If the connection is dropped unexpectedly. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ public void refreshRecordCache() throws AS400Exception, AS400SecurityException, InterruptedException, IOException { // If we are caching, refresh the cache with records starting from the beginning // of the file. if (cacheRecords_) { positionCursorBeforeFirst(); // Set cache direction to FORWARD cache_.currentDirection_ = DDMRecordCache.FORWARD; refreshCache(null, DDMRecordCache.FORWARD, true, false); } } //@RBA public void refreshRecordCacheLong() throws AS400Exception, AS400SecurityException, InterruptedException, IOException { // If we are caching, refresh the cache with records starting from the beginning // of the file. if (cacheRecords_) { positionCursorBeforeFirst(); // Set cache direction to FORWARD cache_.currentDirection_ = DDMRecordCache.FORWARD; refreshCacheLong(null, DDMRecordCache.FORWARD, true, false); } } /** *Rolls back any transactions since the last commit/rollback boundary. Invoking this *method will cause all transactions under commitment control for this connection *to be rolled back. This means that any AS400File object for which a commit *lock level was specified and that was opened under this connection will have *outstanding transactions rolled back. *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ public abstract void rollback() throws AS400Exception, AS400SecurityException, InterruptedException, IOException; //@E2A // This method should be static, but we can't make a static call to // a native method (the call to execute()) so we just set all of the // necessary state variables and act like we're a normal object. public void rollback(AS400Impl system) throws AS400Exception, AS400SecurityException, InterruptedException, IOException { if (isCommitmentControlStarted(system)) { // Setup state variables setSystem(system); setConverter(); rollback(); } } /** *Updates the record at the current cursor position. The cursor must be positioned to an active record. The *last operation on the file must have been a cursor positioning operation or a *read operation. If an attempt is made to update a record more than once without *reading the record or positioning the cursor to the record in between updates, an *AS400Exception is thrown. The cursor position is not changed when this method *is invoked. *@param record The record with which to update. The record must be a record whose *format matches the record format of this object. To ensure that this *requirement is met, use the *RecordFormat.getNewRecord() *method to obtain a default record whose fields can be set appropriately by *the Java program and then written to the file. *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the server. **/ public abstract void update(Record record) throws AS400Exception, AS400SecurityException, InterruptedException, IOException; /** *Writes an array of records to the end of the file. *The cursor is positioned to after the last record of the file as a *result of invoking this method. *@param records The records to write. The records must have a format *which matches the record format of this object. To ensure that this *requirement is met, use the *RecordFormat.getNewRecord() *method to obtain default records whose fields can be set appropriately *by the Java program and then written to the file. *@exception AS400Exception If the server returns an error message. *@exception AS400SecurityException If a security or authority error occurs. *@exception InterruptedException If this thread is interrupted. *@exception IOException If an error occurs while communicating with the *server. **/ public abstract void write(Record[] records) throws AS400Exception, AS400SecurityException, InterruptedException, IOException; }




  • © 2015 - 2024 Weber Informatics LLC | Privacy Policy