/*****************************************************************************/
/* File name: TarFileSystem.java                                             */
/* Purpose: to represent a tar file archive as a filesystem                  */
/*                                                                           */
/* Last modified: 15.08.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*                                                                           */
/* This program is distributed in the hope that it will be useful, but       */
/* WITHOUT ANY WARRANTY; without even the implied warranty of                */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General */
/* Public License for more details.                                          */
/*                                                                           */
/* This software is distributed under the terms                              */
/* of the GNU General Public License as published                            */
/* by the Free Software Foundation; either version 2, or (at your option)    */
/* any later version.                                                        */
/* See file COPYING for your rights (GNU GPL)                                */
/*****************************************************************************/

package io;

import java.io.*;
import java.util.*;
import java.lang.reflect.*;
import jtar.*;
import mount.*;


public
class

TarFileSystem
                   implements FileSystemable,
                              Filable,
                              Serializable

{

  private final static java.lang.String RCSID =
"$Header: /d/NFS/io/RCS/TarFileSystem.java,v 1.7 1999/08/15 23:38:53 vklimov Exp $";


  protected Class   fileableClass = null;
  protected AllActions allActions = null;
  protected java.lang.String path = null;
  protected java.lang.String name = null;
  protected int size = 0;
  protected TarFileSystem parentDirectory = null;
  protected TarFileSystemVector elements = null;
  protected int type = THIS_IS_A_DIRECTORY;
  private Fhandle fileHandle = null;
  private String cacheDir = null;

  private final static java.lang.String TO_STRING_INDENT_STRING = "  ";

  private final static int MAX_DEPTH = 10;
  private static int depth = 0;


  public

  TarFileSystem( java.lang.String archivePath,
                 AllActions allActions,
                 String cacheDir                ) throws NullPointerException
/*****************************************************************************/
/* Function name: TarFileSystem                                              */
/* File name: TarFileSystem.java                                             */
/* Purpose: constructor for the TarFileSystem class                          */
/* Parameters: archivePath                                                   */
/*             allActions                                                    */
/*             cacheDir                                                      */
/* Throws: NullPointerException                                              */
/* Returns:                                                                  */
/* Last modified: 10.08.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
      boolean result = false;
                                                       /* TarFileSystem */
/*---------------------------------------------------------------------------*/

      if (name == null)
        name = File.separator;
      else
        ;
    /*end of if*/

      if (path == null)
        path = File.separator;
      else
        ;
    /*end of if*/

      if (archivePath == null)
        {
          throw new                                        /* throw ! */
            NullPointerException(
             "TarFileSystem, constructor: " +
             "archivePath == null!" );
        }
      else
        ;
    /*end of if*/

      this.allActions = allActions;
      this.cacheDir = cacheDir;

      allActions.archiveName = archivePath.trim();

      if ( (allActions == null) ||
           (allActions.table == null) ) return;             /* return ! */

      result = 
        allActions.table.action(
          (Vector) null,
          (Header) null,
          (BufferRead) null,
          true,              /* fill up */
          (io.TarFileSystem) this, /* the ram filesystem */
          allActions               );

      fileableClass = TarFileSystem.class;

    }
/*end of TarFileSystem*/


  private

  TarFileSystem( java.lang.String name,
                 java.lang.String path,
                 int type,
                 int size,
                 TarFileSystem parentDirectory,
                 String cacheDir,
                 AllActions allActions          )
/*****************************************************************************/
/* Function name: TarFileSystem                                              */
/* File name: TarFileSystem.java                                             */
/* Purpose: constructor for the TarFileSystem class                          */
/* Parameters: name                                                          */
/*             path                                                          */
/*             type                                                          */
/*             size                                                          */
/*             parentDirectory                                               */
/*             cacheDir                                                      */
/*             allActions                                                    */
/* Returns:                                                                  */
/* Last modified: 10.08.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
                                                           /* TarFileSystem */
/*---------------------------------------------------------------------------*/

      this.name = name;
      this.path = path;
      this.type = type;
      this.size = size;
      this.parentDirectory = parentDirectory;
      this.cacheDir = cacheDir;
      this.allActions = allActions;

    }
/*end of TarFileSystem*/


  public
  boolean

  addElement( java.lang.String path,
              int type,
              int size               )
/*****************************************************************************/
/* Function name: addElement                                                 */
/* File name: TarFileSystem.java                                             */
/* Purpose: to insert an element into the tree                               */
/*          This method scans the tree from the root and determines          */
/*          the place where to put the element according to the rules        */
/*          of the local OS                                                  */
/*    Note: leading and trailing path separators are removed                 */
/* Parameters: path                                                          */
/*             type - should be io.Filable.THIS_IS_A_DIRECTORY or            */
/*                              io.Filable.THIS_IS_A_REGULAR_FILE            */
/*             size                                                          */
/* Returns: true - if added OK, false - otherwise                            */
/* Last modified: 10.08.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
      boolean result = false;
      java.lang.String originalPath = null;
      java.lang.String firstDirName = null;
      TarFileSystem existingDir = null;
      int separatorPlaceInThePath =
            general.Constants.JAVA_ERROR_CODE;
      int pathPlaceInElementsVector =
            general.Constants.JAVA_ERROR_CODE;
                                                         /* addElement */
/*---------------------------------------------------------------------------*/

      if (elements == (TarFileSystemVector) null)
        elements = new TarFileSystemVector();
      else
        ;
    /*end of if on null*/

      path = path.trim();

      if ( path.startsWith( File.separator ) )
        path =
          util.String.
            removeLeadingPathSeparator( path );
      else
        ;
    /*end of if*/

      if ( path.endsWith( File.separator ) )
        path =
          util.String.
            removeTrailingPathSeparator( path );
      else
        ;
    /*end of if*/

      originalPath = path;

      separatorPlaceInThePath =
        path.indexOf( File.separator );

      if (separatorPlaceInThePath ==                   /* single file name */
          general.Constants.JAVA_ERROR_CODE)
        {
          pathPlaceInElementsVector =
            elements.indexOfAName( path );

          if (pathPlaceInElementsVector !=            /* file already exists */
              general.Constants.JAVA_ERROR_CODE)
            {
              return false;                                  /* return ! */
            }
          else                       /* not found, may add the element here */
            {                               /* first order element */
               elements.
                  addElement( new
                              TarFileSystem( path, path,
                                             type, size, this, cacheDir,
                                             allActions                  ) );

               return true;                                   /* return ! */

            }
        /*end of if on pathPlaceInElementsVector*/

        }
      else /* this is a path, containing at least one separator */
        {
          firstDirName =
            path.substring( 0, separatorPlaceInThePath );
          path =
            path.substring( separatorPlaceInThePath );

          pathPlaceInElementsVector =
            elements.indexOfAName( firstDirName );

          if (pathPlaceInElementsVector !=           /* something does exist */
              general.Constants.JAVA_ERROR_CODE)
            {
              try
                {
                  existingDir = (TarFileSystem)
                    elements.elementAt(
                      pathPlaceInElementsVector );
                  if (existingDir.type !=             /* this is NOT a dir ! */
                      io.Filable.THIS_IS_A_DIRECTORY)
                    {
                      return false;                              /* return ! */
                    }
                  else
                    {
                      result =
                        existingDir.addElement(
                          originalPath, path, type, size );
                      return result;                           /* return ! */
                    }
                /*end of if on type*/
                }
              catch( ArrayIndexOutOfBoundsException e ) /* no such element*/
                {
                  elements.
                    addElement( new
                      TarFileSystem( firstDirName, firstDirName,
                                     io.Filable.THIS_IS_A_DIRECTORY,
                                     size,
                                     this, cacheDir,
                                     allActions                       ) );
                }
            /*end of try-catch*/
            }
          else /* add a new directory */
            {
              elements.
                addElement( new
                  TarFileSystem( firstDirName, firstDirName,
                                 io.Filable.THIS_IS_A_DIRECTORY,
                                 size, this, cacheDir, allActions ) );

            }
        /*end of if on pathPlaceInElementsVector*/

          result =
            addElement( originalPath, originalPath, type, size );
        }
    /*end of if on separatorPlaceInThePath*/

      return result;

     }
/*end of addElement*/


  private
  boolean

  addElement( java.lang.String originalPath,
              java.lang.String path,
              int type,
              int size                        )
/*****************************************************************************/
/* Function name: addElement                                                 */
/* File name: TarFileSystem.java                                             */
/* Purpose: to insert an element into the tree - this method determines      */
/*          the place where to put the element according to the rules        */
/*          of the local OS                                                  */
/* Parameters: originalPath - this is the path with which the public method  */
/*                            was called, only leading and trailing path     */
/*                            separator were removed if there were           */
/*             path - one or more leading directory names already removed    */
/*                    from this string                                       */
/*             type - should be io.Filable.THIS_IS_A_DIRECTORY or            */
/*                              io.Filable.THIS_IS_A_REGULAR_FILE            */
/*             size                                                          */
/* Returns: true - if added OK, false - otherwise                            */
/* Last modified: 10.08.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
      boolean result = false;
      java.lang.String firstDirName = null;
      java.lang.String firstDirPath = null;
      java.lang.String pathWithFirstDir = null;
      int pathPlaceInFirstDirPath;
      TarFileSystem existingDir = null;
      int separatorPlaceInThePath =
            general.Constants.JAVA_ERROR_CODE;
      int pathPlaceInElementsVector =
            general.Constants.JAVA_ERROR_CODE;
                                                         /* addElement */
/*---------------------------------------------------------------------------*/

      if (elements == (TarFileSystemVector) null)
        elements = new TarFileSystemVector();
      else
        ;
    /*end of if on null*/

      path = path.trim();

      if ( path.startsWith( File.separator ) )
        path =
          util.String.
            removeLeadingPathSeparator( path );
      else
        ;
    /*end of if*/

      if ( path.endsWith( File.separator ) )
        path =
          util.String.
            removeTrailingPathSeparator( path );
      else
        ;
    /*end of if*/

      separatorPlaceInThePath =
        path.indexOf( File.separator );

      if (separatorPlaceInThePath ==                   /* single file name */
          general.Constants.JAVA_ERROR_CODE)
        {
          pathPlaceInElementsVector =
            elements.indexOfAName( path );

          if (pathPlaceInElementsVector !=            /* file already exists */
              general.Constants.JAVA_ERROR_CODE)
            {
              return false;                                  /* return ! */
            }
          else                       /* not found, may add the element here */
            {                               /* first order element */
              elements.
                addElement( new
                  TarFileSystem( path, originalPath, type,
                                 size, this, cacheDir, allActions ) );

              return true;                                   /* return ! */
            }
        /*end of if on pathPlaceInElementsVector*/

        }
      else /* this is a path, containing at least one separator */
        {
          pathWithFirstDir = path;
          firstDirName =
            path.substring( 0, separatorPlaceInThePath );
          path =
            path.substring( separatorPlaceInThePath );

          firstDirPath = originalPath;
          pathPlaceInFirstDirPath =
            firstDirPath.lastIndexOf( path );
          firstDirPath =
            firstDirPath.substring( 0,
                                    pathPlaceInFirstDirPath );

          pathPlaceInElementsVector =
            elements.indexOfAName( firstDirName );

          if (pathPlaceInElementsVector !=           /* something does exist */
              general.Constants.JAVA_ERROR_CODE)
            {
              try
                {
                  existingDir = (TarFileSystem)
                    elements.elementAt(
                      pathPlaceInElementsVector );
                  if (existingDir.type !=             /* this is NOT a dir ! */
                      io.Filable.THIS_IS_A_DIRECTORY)
                    {
                      return false;                              /* return ! */
                    }
                  else
                    {
                      result =
                        existingDir.addElement(
                          originalPath, path, type, size );
                      return result;                           /* return ! */
                    }
                /*end of if on type*/
                }
              catch( ArrayIndexOutOfBoundsException e ) /* no such element*/
                {
                  elements.
                    addElement( new
                      TarFileSystem( firstDirName, firstDirPath,
                                     io.Filable.THIS_IS_A_DIRECTORY,
                                     size, this, cacheDir, allActions ) );
                }
            /*end of try-catch*/
            }
          else /* add a new directory */
            {
                elements.
                  addElement( new
                    TarFileSystem( firstDirName, firstDirPath,
                                   io.Filable.THIS_IS_A_DIRECTORY,
                                   size, this, cacheDir, allActions ) );

            }
        /*end of if on pathPlaceInElementsVector*/

          result =
            addElement( originalPath, pathWithFirstDir, type, size );

        }
    /*end of if on separatorPlaceInThePath*/

      return result;

     }
/*end of addElement*/


  public
  Class

  getFileClass()
/*****************************************************************************/
/* Function name: getFileClass                                               */
/* File name: TarFileSystem.java                                             */
/* Purpose: return the Class to access elements of a tar archive             */
/* Parameters:                                                               */
/* Throws:                                                                   */
/* Returns:                                                                  */
/* Last modified: 08.08.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
                                                       /* getFileClass */
/*---------------------------------------------------------------------------*/

      return (Class) TarFileSystem.class;
    }
/*end of getFileClass*/


  public
  void

  setFileHandle( Fhandle fileHandle )
/*****************************************************************************/
/* Function name: setFileHandle                                              */
/* File name: TarFileSystem.java                                             */
/* Purpose: to set file handle                                               */
/* Parameters: fileHandle                                                    */
/* Throws:                                                                   */
/* Returns:                                                                  */
/* Last modified: 08.08.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
                                                       /* setFileHandle */
/*---------------------------------------------------------------------------*/

      this.fileHandle = fileHandle;

    }
/*end of setFileHandle*/


  public
  Filable

  getFilableInstance( java.lang.String path )
/*****************************************************************************/
/* Function name: getFilableInstance                                         */
/* File name: TarFileSystem.java                                             */
/* Purpose: return a Filable object to access an element of a tar archive    */
/* Parameters: path                                                          */
/* Throws:                                                                   */
/* Returns: the Filable object or null in case of an error                   */
/* Last modified: 08.08.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
      int prefixLength;
      Filable result = null;
                                                 /* getFilableInstance */
/*---------------------------------------------------------------------------*/

      path = path.trim();

      if ( allActions.archiveName.equals( path ) )
        {
          result = this;
        }
      else
        {

          if (path.startsWith( allActions.archiveName )) /* remove prefix */
            {
              prefixLength =
                allActions.archiveName.length();
              path = path.substring( prefixLength );
            }
          else
            ;
        /*end of if*/

          result = (Filable) findElement( path );
        }
    /*end of if*/

      return result;
    }
/*end of getFilableInstance*/


  public
  TarFileSystem

  findElement( java.lang.String path )
/*****************************************************************************/
/* Function name: findElement                                                */
/* File name: TarFileSystem.java                                             */
/* Purpose: to get an element from the root object of the tree               */
/*          This method scans the tree from the root and returns             */
/*          the TarFileSystem object with the given path                     */
/*    Note: leading and trailing path separators do not count                */
/* Parameters: path                                                          */
/* Returns: the TarFileSystem object or                                      */
/*          null if not found                                                */
/* Last modified: 08.08.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
      TarFileSystem result = null;
      java.lang.String originalPath = null;
      java.lang.String firstDirName = null;
      java.lang.String elementsString = "";
      int nElements;
      int i;
      TarFileSystem existingDir = null;
      int separatorPlaceInThePath =
            general.Constants.JAVA_ERROR_CODE;
      int pathPlaceInElementsVector =
            general.Constants.JAVA_ERROR_CODE;
                                                         /* findElement */
/*---------------------------------------------------------------------------*/

      if (elements == (TarFileSystemVector) null)
        {
          return null;                                   /* return ! */
        }
      else
        {
        }
    /*end of if on null*/

      path = path.trim();

      if (path.equals( File.separator ) )
        {
          return this;                                   /* return ! */
        }
      else
        ;
    /*end of if on separator*/

      if ( path.startsWith( File.separator ) )
        path =
          util.String.
            removeLeadingPathSeparator( path );
      else
        ;
    /*end of if*/

      if ( path.endsWith( File.separator ) )
        path =
          util.String.
            removeTrailingPathSeparator( path );
      else
        ;
    /*end of if*/

      originalPath = path;

      separatorPlaceInThePath =
        path.indexOf( File.separator );

      if (separatorPlaceInThePath ==                   /* single file name  */
          general.Constants.JAVA_ERROR_CODE)           /* should be here or */
        {                                              /* there is no such  */
                                                       /* thing at all      */

          pathPlaceInElementsVector =
            elements.indexOfAName( path );

          if (pathPlaceInElementsVector !=             /* file does exist */
              general.Constants.JAVA_ERROR_CODE)
            {
              try
                {
                  result =
                    getElement(
                      pathPlaceInElementsVector );

                  return result;                              /* return ! */
                }
              catch( ArrayIndexOutOfBoundsException e )
                {
                  return null;                                  /* return ! */
                }
            /*end of try-catch*/
            }
          else                                                 /* not found */
            {
              return null;                                     /* return ! */
            }
        /*end of if on pathPlaceInElementsVector*/

        }
      else /* this is a path, containing at least one separator */
        {
          firstDirName =
            path.substring( 0, separatorPlaceInThePath );
          path =
            path.substring( separatorPlaceInThePath );

          pathPlaceInElementsVector =
            elements.indexOfAName( firstDirName );

          if (pathPlaceInElementsVector !=           /* something does exist */
              general.Constants.JAVA_ERROR_CODE)
            {
              try
                {
                  existingDir = (TarFileSystem)
                    elements.elementAt(
                      pathPlaceInElementsVector );
                  if (existingDir.type !=             /* this is NOT a dir ! */
                      io.Filable.THIS_IS_A_DIRECTORY)
                    {
                      return null;                              /* return ! */
                    }
                  else
                    {
                      result =
                        existingDir.findElement( path );

                      return result;                           /* return ! */
                    }
                /*end of if on type*/
                }
              catch( ArrayIndexOutOfBoundsException e ) /* no such element*/
                {
                  return null;                                 /* return ! */
                }
            /*end of try-catch*/
            }
          else /* not found */
            {
              return null;                                     /* return ! */
            }
        /*end of if on pathPlaceInElementsVector*/

        }
    /*end of if on separatorPlaceInThePath*/

     }
/*end of findElement*/


  public
  TarFileSystem

  getElement( int numberOfElement ) throws ArrayIndexOutOfBoundsException
/*****************************************************************************/
/* Function name: getElement                                                 */
/* File name: TarFileSystem.java                                             */
/* Purpose: to get an element from the current TarFileSystem object          */
/* Parameters: numberOfElement                                               */
/* Returns: the TarFileSystem object representing the element                */
/* Throws:  ArrayIndexOutOfBoundsException if numberOfElement is not valid   */
/* Last modified: 08.08.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
                                                         /* getElement */
/*---------------------------------------------------------------------------*/

      if ( (elements == (TarFileSystemVector) null)        ||
           (type != io.Filable.THIS_IS_A_DIRECTORY )
         )
        throw new ArrayIndexOutOfBoundsException();         /* throw ! */
      else
        ;
    /*end of if on null*/

      return (TarFileSystem) elements.elementAt( numberOfElement );

     }
/*end of getElement*/


  public
  int

  elementCount()
/*****************************************************************************/
/* Function name: elementCount                                               */
/* File name: TarFileSystem.java                                             */
/* Purpose: to get the number of elements in this TarFileSystem object       */
/*          representing a directory                                         */
/* Parameters:                                                               */
/* Returns: number of elements                                               */
/* Last modified: 08.08.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
                                                         /* elementCount */
/*---------------------------------------------------------------------------*/

      if ( (elements == (TarFileSystemVector) null)        ||
           (type != io.Filable.THIS_IS_A_DIRECTORY )
         )
        return 0;                                            /* return ! */
      else
        ;
    /*end of if on null*/

      return elements.size();

     }
/*end of elementCount*/


  private
  java.lang.String

  toString0( java.lang.String indentPrefix )
/*****************************************************************************/
/* Function name: toString0                                                  */
/* File name: TarFileSystem.java                                             */
/* Purpose: to represent a file tree under a dir element as a string         */
/* Parameters: indentPrefix                                                  */
/* Returns: the string representation of the file tree                       */
/* Last modified: 08.08.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
      int i;
      TarFileSystem currentElement;
      int nElements;
      java.lang.String result = new java.lang.String();
                                                         /* toString0 */
/*---------------------------------------------------------------------------*/

      indentPrefix =
        indentPrefix + TO_STRING_INDENT_STRING;

      if (elements == (TarFileSystemVector) null)
        {
          result = result + indentPrefix + "nothing\n";
          return result;                                    /* return ! */
        }
      else
        ;
    /*end of if on null*/

      nElements = elements.size();
      i=0;
      while( i < nElements )
        {
          result = result + indentPrefix +
            ( (TarFileSystem) elements.elementAt(i)).name +
            "\n";
          i++;
        }
    /*end of while-loop*/
      result = result + "\n";
                                                       /* list subdirs */
      i=0;
      while( i < nElements )
        {
          currentElement = (TarFileSystem) elements.elementAt(i);
          if (currentElement.type ==
              io.Filable.THIS_IS_A_DIRECTORY)
            {
              result = result + "\n" + indentPrefix +
                "Directory " +
                currentElement.name + " contains:\n";
              result = result +
                currentElement.toString0( indentPrefix );
            }
          else
            result = result + " size=" + size;
        /*end of if on THIS_IS_A_DIRECTORY*/
          i++;
        }
    /*end of while-loop*/
      if (nElements == 0)
        result = result + indentPrefix + "nothing\n";
      else
        ;
    /*end of if on 0*/

      return result;

     }
/*end of toString0*/


  public
  java.lang.String

  toStringFully()
/*****************************************************************************/
/* Function name: toStringFully                                              */
/* File name: TarFileSystem.java                                             */
/* Purpose: to represent the file tree as a string                           */
/* Parameters:                                                               */
/* Returns: the string representation of the file tree                       */
/* Last modified: 08.08.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
      int i;
      TarFileSystem currentElement;
      int nElements;
      java.lang.String result = new java.lang.String();
                                                         /* toStringFully */
/*---------------------------------------------------------------------------*/

      result = toString();

      if (elements == (TarFileSystemVector) null)
        return result;                                    /* return ! */
      else
        ;
    /*end of if on null*/

      nElements = elements.size();
      i=0;
      while( i < nElements )
        {
          result = result +
            ( (TarFileSystem) elements.elementAt(i)).name +
            "\n";
          i++;
        }
    /*end of while-loop*/
      result = result + "\n";
                                                       /* list subdirs */
      i=0;
      while( i < nElements )
        {
          currentElement = (TarFileSystem) elements.elementAt(i);
          if (currentElement.type ==
              io.Filable.THIS_IS_A_DIRECTORY)
            {
              result = result + "\nDirectory " +
                currentElement.name + " contains:\n";
              result = result +
                currentElement.toString0( "" );
            }
          else
            ;
        /*end of if on THIS_IS_A_DIRECTORY*/
          i++;
        }
    /*end of while-loop*/

      return result;

     }
/*end of toStringFully*/


  public
  java.lang.String

  toString()
/*****************************************************************************/
/* Function name: toString                                                   */
/* File name: TarFileSystem.java                                             */
/* Purpose: to represent the object as a string                              */
/* Parameters:                                                               */
/* Throws:                                                                   */
/* Returns: the String                                                       */
/* Last modified: 05.08.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
      java.lang.String result = "";
                                                          /* toString */
/*---------------------------------------------------------------------------*/

      result += "TarFileSystem,\n";
      result += ( (fileableClass == null) ?
                  ("fileableClass==null") :
                  ("fileableClass=" +
                    fileableClass.toString()) ) + "\n";
      result += ( (allActions == null) ?
                  ("allActions==null") :
                  ("allActions.archiveName=" +
                    allActions.archiveName)    ) + "\n";
      result += ( (path == null) ?
                  ("path==null") :
                  ("path=" + path)    ) +
                ( (name == null) ?
                  (" name==null") :
                  (" name=" + name)    ) + "\n";
      result += ( (parentDirectory == null) ?
                  ("parentDirectory==null") :
                  ("parentDirectory is set to something")    );
      switch( type )
        {
        case io.Filable.THIS_IS_A_REGULAR_FILE:
          result += " type=THIS_IS_A_REGULAR_FILE";
          break;
        case io.Filable.THIS_IS_A_DIRECTORY:
          result += " type=THIS_IS_A_DIRECTORY";
          break;
        default:
          result += " unknown type=" + type;
          break;
        }
    /*end of switch on type*/

      result += "\n";

      result += ( (elements == null) ?
                  ("elements==null") :
                  ("there are " +
                   elements.size() +
                   " elements")    ) +              "\n";

      return result;

    }
/*end of toString*/


  public
  java.lang.String[]

  list()
/*****************************************************************************/
/* Function name: list                                                       */
/* File name: TarFileSystem.java                                             */
/* Purpose: to return an array of file names contained in this TarFileSystem */
/*          object representing a directory                                  */
/* Parameters:                                                               */
/* Returns: array of file names or                                           */
/*          null if this is not a directory or there is no files in it       */
/* Last modified: 08.08.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
      int i;
      TarFileSystem currentElement;
      int nElements;
      java.lang.String[] resultArray = null;
                                                           /* list */
/*---------------------------------------------------------------------------*/

      if (elements == (TarFileSystemVector) null)
        return null;                                       /* return ! */
      else
        ;
    /*end of if on null*/

      nElements = elements.size();
      resultArray = new java.lang.String[ nElements ];
      i=0;
      while( i < nElements )
        {
          resultArray[i] =
            ( (TarFileSystem) elements.elementAt(i)).name;
          i++;
        }
    /*end of while-loop*/

      return resultArray;

    }
/*end of list*/


  public
  java.lang.String

  getParent()
/*****************************************************************************/
/* Function name: getParent                                                  */
/* File name: TarFileSystem.java                                             */
/* Purpose: to return path of the parent directory of this TarFileSystem     */
/*          object                                                           */
/* Parameters:                                                               */
/* Returns: the path string or                                               */
/*          null if there is no parent directory                             */
/* Last modified: 08.08.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
                                                          /* getParent */
/*---------------------------------------------------------------------------*/

      if (parentDirectory == (TarFileSystem) null)
        {
          return null;                                     /* return ! */
        }
      else
        ;
    /*end of if on null*/

      return parentDirectory.path;
             

    }
/*end of getParent*/


  public
  boolean

  exists()
/*****************************************************************************/
/* Function name: exists                                                     */
/* File name: TarFileSystem.java                                             */
/* Purpose: always returns true for this file system                         */
/* Parameters:                                                               */
/* Returns: true                                                             */
/* Last modified: 08.08.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
                                                          /* exists */
/*---------------------------------------------------------------------------*/

      return true;

    }
/*end of exists*/


  public
  boolean

  isDirectory()
/*****************************************************************************/
/* Function name: isDirectory                                                */
/* File name: TarFileSystem.java                                             */
/* Purpose: to return true if this TarFileSystem object represents           */
/*          a directory                                                      */
/* Parameters:                                                               */
/* Returns: true if this is a directory                                      */
/*          false - if this not a directory                                  */
/* Last modified: 08.08.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
                                                       /* isDirectory */
/*---------------------------------------------------------------------------*/

      if (type == THIS_IS_A_DIRECTORY)
        return true;
      else
        return false;
    /*end of if*/

    }
/*end of isDirectory*/


  public
  java.lang.String

  getCanonicalPath() throws java.io.IOException
/*****************************************************************************/
/* Function name: getCanonicalPath                                           */
/* File name: TarFileSystem.java                                             */
/* Purpose: this method returns just the path string that we have            */
/*          for this TarFileSystem object for this file system               */
/* Parameters:                                                               */
/* Throws: IOException                                                       */
/* Returns: the path string or                                               */
/*          null if there is no path                                         */
/* Last modified: 08.08.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
                                                  /* getCanonicalPath */
/*---------------------------------------------------------------------------*/

      return path;

    }
/*end of getCanonicalPath*/


  public
  boolean

  isFile()
/*****************************************************************************/
/* Function name: isFile                                                     */
/* File name: TarFileSystem.java                                             */
/* Purpose: to true if this TarFileSystem object represents a regular file   */
/* Parameters:                                                               */
/* Returns: true - if the is a regular file                                  */
/*          false - otherwise                                                */
/* Last modified: 08.08.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
                                                         /* isFile */
/*---------------------------------------------------------------------------*/

      if (type == THIS_IS_A_REGULAR_FILE)
        return true;
      else
        return false;
    /*end of if*/

    }
/*end of isFile*/


  public
  java.lang.String

  getName()
/*****************************************************************************/
/* Function name: getName                                                    */
/* File name: TarFileSystem.java                                             */
/* Purpose: to return the name string of this TarFileSystem object           */
/* Parameters:                                                               */
/* Returns: the name string                                                  */
/* Last modified: 08.08.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
                                                       /* getName */
/*---------------------------------------------------------------------------*/

      return name;

    }
/*end of getName*/


  public
  Fhandle

  getFileHandle()
/*****************************************************************************/
/* Function name: getFileHandle                                              */
/* File name: TarFileSystem.java                                             */
/* Purpose: to return the file handle of this TarFileSystem object           */
/* Parameters:                                                               */
/* Returns: the file handle                                                  */
/* Last modified: 09.08.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
                                                       /* getFileHandle */
/*---------------------------------------------------------------------------*/

      return fileHandle;

    }
/*end of getFileHandle*/


  public
  InputStream

  openInputStream()
/*****************************************************************************/
/* Function name: openInputStream                                            */
/* File name: TarFileSystem.java                                             */
/* Purpose: to open an input stream to read from the file represented        */
/*          by this TarFileSystem object                                     */
/* Parameters:                                                               */
/* Returns: the input stream object or                                       */
/*          null in case of an error                                         */
/* Last modified: 11.08.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
      boolean result;
      NamesFilesInputOutput namesInputOutput = null;
      Vector namesToExtractVector = null;
      InputStream resultInputStream = null;
      boolean cacheFileDoesExist;
      File file = null;
      String cacheFileName = null;
      String dirPath = null;
      long fileId = 0;
      int placeEndOfArchiveName;
                                                       /* openInputStream */
/*---------------------------------------------------------------------------*/

      fileId = fileHandle.getFileId();
      cacheFileName = (new Long( fileId ) ).toString() +
                       Constants.CACHE_FILE_EXTENTION;

      if (cacheDir != null)
        {
          cacheFileName = cacheDir + File.separator +
            cacheFileName;
          file = new File( cacheFileName );
        }
      else /* cacheDir is null, use current dir */
        {
          file = new File( cacheFileName );
        }
    /*end of if on cacheDir*/

      dirPath = fileHandle.getDirPath();

      try
        {
          cacheFileDoesExist = file.exists();
          if (cacheFileDoesExist)
            {
            }
          else /* extract into cache file */
            {
              if (dirPath.startsWith( allActions.archiveName ))
                {
                  placeEndOfArchiveName = allActions.archiveName.length();
                  dirPath = dirPath.substring(
                    placeEndOfArchiveName );
                  dirPath = util.String.
                    removeLeadingPathSeparator( dirPath );

                  if ( (allActions == null) ||
                       (allActions.table == null) ) return null; /* return ! */

                  namesToExtractVector = new Vector();

                  namesInputOutput = new
                    NamesFilesInputOutput( dirPath,
                                           cacheFileName );

                  namesToExtractVector.
                    addElement( (Object)
                      namesInputOutput );

                  result = 
                    allActions.extract.action(
                      namesToExtractVector,
                      (Header) null,
                      (BufferRead) null,
                      allActions               );

                  if (!result) return null;               /* return ! */

                }
              else
                ;
            /*end of if on allActions.archiveName*/

            }
        /*end of if on cacheFileDoesExist*/

          resultInputStream =  new
            FileInputStream( cacheFileName );

          return resultInputStream;                        /* return ! */

        }
      catch( FileNotFoundException e )
        {
          System.out.println( "TarFileSystem, openInputStream: " +
                              "FileNotFoundException, " +
                              e.getMessage()                        );
          return null;
        }
      catch( SecurityException e )
        {
          System.out.println( "TarFileSystem, openInputStream: " +
                              "SecurityException, " +
                              e.getMessage()                        );
          return null;
        }
    /*end of try-catch*/

    }
/*end of openInputStream*/


  public
  static
  void

  removeAllCacheFiles( String cacheDir )
/*****************************************************************************/
/* Function name: removeAllCacheFiles                                        */
/* File name: TarFileSystem.java                                             */
/* Purpose: to remove all cache files extracted earlier                      */
/* Parameters: cacheDir                                                      */
/* Returns:                                                                  */
/* Last modified: 14.08.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
      boolean result;
      boolean removeThisFile;
      int i;
      File file = null;
      File dirFile = null;
      String cacheFileName = null;
      String[] filesList = null;
      String dirPath = null;
      StringBuffer currentDirAbbrev;
                                                  /* removeAllCacheFiles */
/*---------------------------------------------------------------------------*/

      try
        {
          if (cacheDir != null)
            {
              dirFile = new File( cacheDir );
            }
          else /* cacheDir is null, use current dir */
            {
              currentDirAbbrev = new StringBuffer();
              currentDirAbbrev.append(
                general.Constants.CURRENT_DIRECTORY_ABBREVIATION );
              dirFile = new File( currentDirAbbrev.toString() );
            }
        /*end of if on cacheDir*/

          filesList = dirFile.list();
          for (i = 0; i<filesList.length; i++)
            {
              removeThisFile =
                accept( dirFile, filesList[i] );

              if (removeThisFile)
                {
                  cacheFileName = cacheDir + File.separator +
                    filesList[i];
                  file = new File( cacheFileName );
                  file.delete();
                }
              else
                ;
            /*end of if*/
            }
        /*end of for-loop*/
        }
      catch( SecurityException e )
        {
          System.out.println( "TarFileSystem, removeAllCacheFiles: " +
                              "SecurityException, " +
                              e.getMessage()                        );
          return;
        }
    /*end of try-catch*/

    }
/*end of removeAllCacheFiles*/


  public
  static
  void

  removeCacheFile( long fileId,
                   String cacheDir )
/*****************************************************************************/
/* Function name: removeCacheFile                                            */
/* File name: TarFileSystem.java                                             */
/* Purpose: to the cache file extracted earlier                              */
/* Parameters: fileId                                                        */
/*             cacheDir                                                      */
/* Returns:                                                                  */
/* Last modified: 15.08.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
      boolean result;
      boolean removeThisFile;
      int i;
      File file = null;
      File dirFile = null;
      String cacheFileName = null;
      String[] filesList = null;
      String dirPath = null;
      StringBuffer currentDirAbbrev;
                                                  /* removeCacheFile */
/*---------------------------------------------------------------------------*/

      try
        {

          if (cacheDir != null)
            {
              cacheFileName = cacheDir + File.separator +
                (new Long( fileId ) ).toString() +
                           Constants.CACHE_FILE_EXTENTION;
            }
          else /* cacheDir is null, use current dir */
            {
              cacheFileName =
                (new Long( fileId ) ).toString() +
                           Constants.CACHE_FILE_EXTENTION;
            }
        /*end of if on cacheDir*/

          file = new File( cacheFileName );

          if (file.exists())
            {
              file.delete();
            }
          else
            ;
        /*end of if*/
        }
      catch( SecurityException e )
        {
          System.out.println( "TarFileSystem, removeCacheFile: " +
                              "SecurityException, " +
                              e.getMessage()                        );
          return;
        }
    /*end of try-catch*/

    }
/*end of removeCacheFile*/


  public
  static
  boolean

  accept( File dir,
          String name )
/*****************************************************************************/
/* Function name: accept                                                     */
/* File name: TarFileSystem.java                                             */
/* Purpose: to test whether the specified file should be included in a list  */
/*          of files                                                         */
/* Parameters: dir                                                           */
/*             name                                                          */
/* Returns: true - if the file should be included, false - otherwise         */
/* Last modified: 14.08.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
      boolean continueToLoop = true;
      char character;
      int i;
      int lengthOfExtention;
      int lengthOfName;
      int newLengthOfName;
                                                            /* accept */
/*---------------------------------------------------------------------------*/

      if ( ! name.endsWith(
               Constants.CACHE_FILE_EXTENTION ) ) return false;  /* return ! */

      lengthOfExtention =
        Constants.
          CACHE_FILE_EXTENTION.length();
      lengthOfName = name.length();
      newLengthOfName = lengthOfName - lengthOfExtention;

      name = name.substring( 0, newLengthOfName );

      i = 0;
      while( (i < newLengthOfName) &&
             continueToLoop
           )
        {
          character = name.charAt( i );
          if ( !Character.isDigit( character ) )
            continueToLoop = false;
          else
            i++;
        /*end of if*/
        }
    /*end of while-loop*/

      return continueToLoop;

    }
/*end of accept*/



  public
  java.lang.String
  getPath()
    {

      return "";

    }




  public
  long
  lastModified()
    {

      return 0;

    }


  public
  long

  length()
/*****************************************************************************/
/* Function name: length                                                     */
/* File name: TarFileSystem.java                                             */
/* Purpose: to return the size of this element                               */
/* Parameters:                                                               */
/* Returns: the length                                                       */
/* Last modified: 08.08.99                                                   */
/* Author: Victor Klimov, 1999                                               */
/*****************************************************************************/
    {
                                                       /* length */
/*---------------------------------------------------------------------------*/

      return (long) size;
    }
/*end of length*/


  public
  boolean
  mkdir( java.lang.String dirName )
    {
      return true;
    }


  public
  boolean
  mkdirs( java.lang.String dirName )
    {
      return true;
    }


  public
  boolean

  canRead()
    {
      return true;
    }


  public
  boolean

  canWrite()
    {
      return false;
    }

} /*end of TarFileSystem */

/*****************************************************************************/
/* End of file: TarFileSystem.java                                           */
/*****************************************************************************/
