org.cdlib.xtf.util
Class StructuredFile

Object
  extended by StructuredFile
All Implemented Interfaces:
StructuredStore

public class StructuredFile
extends Object
implements StructuredStore

A simple structured file with a flat top-level directory. Subfiles can be added to an existing file.

Author:
Martin Haye

Nested Class Summary
private  class StructuredFile.Directory
          Maintains the directory of files within a structured file.
private  class StructuredFile.DirEntry
          A single entry in a Directory
 
Field Summary
private  StructuredFile.DirEntry creatingEnt
          Directory entry of the sub-file being created (if creatingSubfile is true).
private  SubFileWriter creatingSubfile
          True when creating a sub-file; enforces the rule that only one sub-file may be created at a time.
(package private)  Object curSubFile
          The sub-file that last accessed the file.
private  StructuredFile.Directory dir
          Current subfile directory
private  int dirPos
          File position of the subfile directory (zero if the directory has been erased)
private  File file
          Actual file path of the structured file
private static HashMap fileMap
          Map of currently open Structured files.
private  int openCount
          Number of currently open Structured files
private  LinkedList openSubfiles
          List of currently opened subfiles
private  RandomAccessFile realFile
          Used to read/write the disk file
static Tester tester
          Regression test to make sure the code works properly.
 
Constructor Summary
private StructuredFile(File file, boolean create)
          Instances should never be created by outside parties, so the constructor is strictly private.
 
Method Summary
 void close()
          Closes the file.
(package private)  void closeReader(SubFileReader subfile)
          Called by a subfile reader when its close() method is called.
(package private)  void closeWriter(SubFileWriter subfile)
          Called by a subfile when its close() method is called.
static StructuredFile create(File file)
          Create a structured file from scratch.
 SubStoreWriter createSubStore(String name)
          Create a new sub-file with the specified name.
 void delete()
          Close and delete the entire structured file
private  void eraseDirectory()
          Gets rid of the directory at the end of the file, in preparation for overwriting it with a new subfile.
 String getSystemId()
          Get the full path to the file
 String getUserVersion()
          Gets the user version (if any) set by setUserVersion(String).
static StructuredFile open(File file)
          Open an existing structured file.
 SubStoreReader openSubStore(String name)
          Opens a pre-existing subfile for read (or write).
private  void readHeader()
          Reads the file header and directory of the structured file.
 void setUserVersion(String ver)
          Sets a user-defined version number for the store.
private  void writeDirectory()
          Writes the current directory at the end of the file.
 
Methods inherited from class Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

file

private File file
Actual file path of the structured file


realFile

private RandomAccessFile realFile
Used to read/write the disk file


dirPos

private int dirPos
File position of the subfile directory (zero if the directory has been erased)


dir

private StructuredFile.Directory dir
Current subfile directory


creatingSubfile

private SubFileWriter creatingSubfile
True when creating a sub-file; enforces the rule that only one sub-file may be created at a time.


creatingEnt

private StructuredFile.DirEntry creatingEnt
Directory entry of the sub-file being created (if creatingSubfile is true).


openSubfiles

private LinkedList openSubfiles
List of currently opened subfiles


curSubFile

Object curSubFile
The sub-file that last accessed the file. This is checked every time a sub-file wants to access the file, to see if the file pointer needs to be saved/restored. Package-private, since the Subfile class needs access to it.


openCount

private int openCount
Number of currently open Structured files


fileMap

private static HashMap fileMap
Map of currently open Structured files. Used to ensure that only one instance of a given file is in memory at any given time, to avoid concurrency problems.


tester

public static final Tester tester
Regression test to make sure the code works properly. Creates a file in the current directory, then erases it.

Constructor Detail

StructuredFile

private StructuredFile(File file,
                       boolean create)
                throws IOException
Instances should never be created by outside parties, so the constructor is strictly private.

Throws:
IOException
Method Detail

getSystemId

public String getSystemId()
Get the full path to the file

Specified by:
getSystemId in interface StructuredStore

readHeader

private void readHeader()
                 throws IOException
Reads the file header and directory of the structured file. Called by constructor.

Throws:
IOException

create

public static StructuredFile create(File file)
                             throws IOException
Create a structured file from scratch. Any existing file is replaced by a new empty one.

Parameters:
file - The file path to write to.
Throws:
IOException

open

public static StructuredFile open(File file)
                           throws FileNotFoundException,
                                  IOException
Open an existing structured file.

Parameters:
file - The file to open.
Throws:
FileNotFoundException - If the file doesn't exist.
IOException

createSubStore

public SubStoreWriter createSubStore(String name)
                              throws IOException
Create a new sub-file with the specified name. Returns a Subfile that has most of the interface of a RandomAccessFile, except that seeks will be relative to the sub-file start. Only one subfile may be created at a time (though many others may be opened, provided they were created before.) The caller must call Subfile.close() when the file is complete, to ensure that the directory gets written.

Specified by:
createSubStore in interface StructuredStore
Parameters:
name - Name of the sub-file to create. Must not exist.
Returns:
A subfile to write to.
Throws:
IOException

openSubStore

public SubStoreReader openSubStore(String name)
                            throws IOException
Opens a pre-existing subfile for read (or write). Returns a subfile that has most of the interface of a RandomAccessFile, except that seeks will be relative to the sub-file start, and IO operations cannot exceed the boundaries of the sub-file. Many subfiles may be open simultaneously; each one has an independent file pointer. Each one is light weight, so it's okay to have many open at a time.

Specified by:
openSubStore in interface StructuredStore
Parameters:
name - Name of pre-existing subfile to open.
Throws:
IOException

closeReader

void closeReader(SubFileReader subfile)
           throws IOException
Called by a subfile reader when its close() method is called.

Parameters:
subfile - The sub-file reader being closed.
Throws:
IOException

closeWriter

void closeWriter(SubFileWriter subfile)
           throws IOException
Called by a subfile when its close() method is called. If the subfile is newly created, we update the directory.

Parameters:
subfile - The sub-file being closed.
Throws:
IOException

setUserVersion

public void setUserVersion(String ver)
                    throws IOException
Sets a user-defined version number for the store. It can be retrieved later with getUserVersion().

Specified by:
setUserVersion in interface StructuredStore
Parameters:
ver - The version number to set.
Throws:
IOException

getUserVersion

public String getUserVersion()
Gets the user version (if any) set by setUserVersion(String).

Specified by:
getUserVersion in interface StructuredStore

close

public void close()
           throws IOException
Closes the file. This should always be called, to ensure that all sub-files have been closed and that the directory has been written.

Specified by:
close in interface StructuredStore
Throws:
IOException

delete

public void delete()
            throws IOException
Close and delete the entire structured file

Specified by:
delete in interface StructuredStore
Throws:
IOException

eraseDirectory

private void eraseDirectory()
                     throws IOException
Gets rid of the directory at the end of the file, in preparation for overwriting it with a new subfile. When the subfile is complete, call writeDirectory() to record the change.

Throws:
IOException

writeDirectory

private void writeDirectory()
                     throws IOException
Writes the current directory at the end of the file. Assumes the previous directory was already erased (by calling eraseDirectory()).

Throws:
IOException