com.mucommander.file
Class AbstractArchiveFile

java.lang.Object
  extended by com.mucommander.file.AbstractFile
      extended by com.mucommander.file.impl.ProxyFile
          extended by com.mucommander.file.AbstractArchiveFile
All Implemented Interfaces:
PermissionAccesses, PermissionTypes
Direct Known Subclasses:
AbstractROArchiveFile, AbstractRWArchiveFile

public abstract class AbstractArchiveFile
extends ProxyFile

AbstractArchiveFile is the superclass of all archive files. It allows archive file to be browsed as if they were regular directories, independently of the underlying protocol used to access the actual file.

AbstractArchiveFile extends ProxyFile to delegate the AbstractFile implementation to the actual archive file and overrides some methods to provide the added functionality.
There are two kinds of AbstractArchiveFile, both of which extend this class:

When implementing a new archive file/format, either AbstractROArchiveFile or AbstractRWArchiveFile should be subclassed, but not this class.

The first time one of the ls() methods is called to list the archive's contents, the getEntries() method is called to retrieve a list of *all* the entries contained by the archive, not only the ones at the top level but also the ones nested one of several levels below. Using this list of entries, it creates a tree to map the structure of the archive and list the content of any particular directory within the archive. This tree is recreated (getEntries() is called again) only if the archive file has changed, i.e. its date has changed since the tree was created.

Files returned by the ls() are ArchiveEntryFile instances which use an ArchiveEntry object to retrieve the entry's attributes. In turn, these ArchiveEntryFile instances query the associated AbstractArchiveFile to list their content.
From an implementation perspective, one only needs to deal with ArchiveEntry instances, all the nuts and bolts are taken care of by this class.

Author:
Maxence Bernard
See Also:
FileFactory, ArchiveFormatProvider, ArchiveEntry, ArchiveEntryFile, Archiver

Field Summary
protected  long entryTreeDate
          Date this file had when the entries tree was created.
protected  ArchiveEntryTree entryTreeRoot
          Archive entries tree
 
Fields inherited from class com.mucommander.file.impl.ProxyFile
file
 
Fields inherited from class com.mucommander.file.AbstractFile
DEFAULT_SEPARATOR, fileURL, IO_BUFFER_SIZE, MUST_HINT, MUST_NOT_HINT, SHOULD_HINT, SHOULD_NOT_HINT, windowsDriveRootPattern
 
Fields inherited from interface com.mucommander.file.PermissionTypes
EXECUTE_PERMISSION, READ_PERMISSION, WRITE_PERMISSION
 
Fields inherited from interface com.mucommander.file.PermissionAccesses
GROUP_ACCESS, OTHER_ACCESS, USER_ACCESS
 
Constructor Summary
protected AbstractArchiveFile(AbstractFile file)
          Creates an AbstractArchiveFile on top of the given file.
 
Method Summary
protected  void addToEntriesTree(ArchiveEntry entry)
          Adds the given ArchiveEntry to the entries tree.
 boolean canRunProcess()
          Always returns false.
protected  void checkEntriesTree()
          Checks if the entries tree exists and if this file hasn't been modified since the tree was last created.
protected  void createEntriesTree()
          Creates the entries tree, used by ls(ArchiveEntryFile, com.mucommander.file.filter.FilenameFilter, com.mucommander.file.filter.FileFilter) to quickly list the contents of an archive's subfolder.
protected  void declareEntriesTreeUpToDate()
          Declares the entries tree up-to-date by setting the current tree date to the archive file's.
protected  AbstractFile getArchiveEntryFile(ArchiveEntry entry, AbstractFile parentFile, boolean exists)
          Creates and returns an AbstractFile using the provided entry and parent file.
 AbstractFile getArchiveEntryFile(java.lang.String entryPath)
          Creates and returns an AbstractFile that corresponds to the given entry path within the archive.
abstract  java.util.Vector getEntries()
          Returns a Vector of ArchiveEntry, representing all the entries this archive file contains.
abstract  java.io.InputStream getEntryInputStream(ArchiveEntry entry)
          Returns an InputStream to read from the given archive entry.
 long getFreeSpace()
          Returns the proxied file's free space if this archive is writable (as reported by isWritableArchive(), else returns 0.
 boolean isBrowsable()
          Always returns true, archive files can be browsed even though they are not directories.
 boolean isDirectory()
          Always returns false, archive files can be browsed but they are not directiories.
abstract  boolean isWritableArchive()
          Returns true if this archive file is writable, i.e.
 AbstractFile[] ls()
          This method is overridden to list and return the topmost entries contained by this archive.
protected  AbstractFile[] ls(ArchiveEntryFile entryFile, FilenameFilter filenameFilter, FileFilter fileFilter)
          Returns the contents of the specified folder entry.
protected  AbstractFile[] ls(javax.swing.tree.DefaultMutableTreeNode treeNode, AbstractFile parentFile, FilenameFilter filenameFilter, FileFilter fileFilter)
          Returns the contents (direct children) of the specified tree node.
 AbstractFile[] ls(FileFilter filter)
          This method is overridden to list and return the topmost entries contained by this archive, filtering out the ones that do not match the specified FileFilter.
 AbstractFile[] ls(FilenameFilter filter)
          This method is overridden to list and return the topmost entries contained by this archive, filtering out the ones that do not match the specified FilenameFilter.
protected  void removeFromEntriesTree(ArchiveEntry entry)
          Removes the given ArchiveEntry from the entries tree.
 AbstractProcess runProcess(java.lang.String[] tokens)
          Always throws an IOException.
 
Methods inherited from class com.mucommander.file.impl.ProxyFile
canChangeDate, canGetGroup, canGetOwner, changeDate, changePermission, changePermissions, copyStream, copyTo, delete, deleteRecursively, equals, exists, getAbsolutePath, getCanonicalFile, getCanonicalPath, getChangeablePermissions, getCopyToHint, getDate, getExtension, getGroup, getInputStream, getInputStream, getJavaNetURL, getMoveToHint, getName, getOutputStream, getOwner, getParent, getPermissions, getPermissionsString, getProxiedFile, getRandomAccessInputStream, getRandomAccessOutputStream, getRoot, getSeparator, getSize, getTotalSpace, getUnderlyingFileObject, getURL, hashCode, hasRandomAccessInputStream, hasRandomAccessOutputStream, importPermissions, importPermissions, isHidden, isRoot, isSymlink, mkdir, mkfile, moveTo, setParent, toString
 
Methods inherited from class com.mucommander.file.AbstractFile
addTrailingSeparator, calculateChecksum, calculateChecksum, calculateChecksum, changePermissions, checkCopyPrerequisites, copyRecursively, deleteRecursively, getAbsolutePath, getAncestor, getAncestor, getCanonicalPath, getChild, getDirectChild, getExtension, getIcon, getIcon, getNameWithoutExtension, getParentArchive, getParentSilently, getTopAncestor, hasAncestor, hasAncestor, isParentOf, mkdir, mkdirs, mkfile, removeTrailingSeparator
 
Methods inherited from class java.lang.Object
clone, finalize, getClass, notify, notifyAll, wait, wait, wait
 

Field Detail

entryTreeRoot

protected ArchiveEntryTree entryTreeRoot
Archive entries tree


entryTreeDate

protected long entryTreeDate
Date this file had when the entries tree was created. Used to detect if the archive file has changed and entries need to be reloaded

Constructor Detail

AbstractArchiveFile

protected AbstractArchiveFile(AbstractFile file)
Creates an AbstractArchiveFile on top of the given file.

Parameters:
file - the file on top of which to create the archive
Method Detail

createEntriesTree

protected void createEntriesTree()
                          throws java.io.IOException
Creates the entries tree, used by ls(ArchiveEntryFile, com.mucommander.file.filter.FilenameFilter, com.mucommander.file.filter.FileFilter) to quickly list the contents of an archive's subfolder.

Throws:
java.io.IOException - if an error occured while retrieving this archive's entries

checkEntriesTree

protected void checkEntriesTree()
                         throws java.io.IOException
Checks if the entries tree exists and if this file hasn't been modified since the tree was last created. If any of those 2 conditions isn't met, the entries tree is (re)created.

Throws:
java.io.IOException - if an error occurred while creating the tree

declareEntriesTreeUpToDate

protected void declareEntriesTreeUpToDate()
Declares the entries tree up-to-date by setting the current tree date to the archive file's. This method should be called by AbstractRWArchiveFile implementations when the archive file has been modified and the entries propagated in the tree, to avoid the tree from being automatically re-created when checkEntriesTree() is called.


addToEntriesTree

protected void addToEntriesTree(ArchiveEntry entry)
                         throws java.io.IOException
Adds the given ArchiveEntry to the entries tree. This method will create the tree if it doesn't already exist, or re-create it if the archive file has changed since it was last created.

Parameters:
entry - the ArchiveEntry to add to the tree
Throws:
java.io.IOException - if an error occurred while creating the entries tree

removeFromEntriesTree

protected void removeFromEntriesTree(ArchiveEntry entry)
                              throws java.io.IOException
Removes the given ArchiveEntry from the entries tree. This method will create the tree if it doesn't already exist, or re-create it if the archive file has changed since it was last created.

Parameters:
entry - the ArchiveEntry to remove from the tree
Throws:
java.io.IOException - if an error occurred while creating the entries tree

ls

protected AbstractFile[] ls(ArchiveEntryFile entryFile,
                            FilenameFilter filenameFilter,
                            FileFilter fileFilter)
                     throws java.io.IOException
Returns the contents of the specified folder entry.

Throws:
java.io.IOException

ls

protected AbstractFile[] ls(javax.swing.tree.DefaultMutableTreeNode treeNode,
                            AbstractFile parentFile,
                            FilenameFilter filenameFilter,
                            FileFilter fileFilter)
                     throws java.io.IOException
Returns the contents (direct children) of the specified tree node.

Throws:
java.io.IOException

getArchiveEntryFile

protected AbstractFile getArchiveEntryFile(ArchiveEntry entry,
                                           AbstractFile parentFile,
                                           boolean exists)
                                    throws java.io.IOException
Creates and returns an AbstractFile using the provided entry and parent file. This method takes care of creating the proper AbstractArchiveFile instance if the entry is itself an archive. The entry file's path will use the separator of the underlying file, as returned by ProxyFile.getSeparator(). That means entries paths of archives located on Windows local filesystems will use '\' as a separator, and '/' for Unix local archives.

Throws:
java.io.IOException

getArchiveEntryFile

public AbstractFile getArchiveEntryFile(java.lang.String entryPath)
                                 throws java.io.IOException
Creates and returns an AbstractFile that corresponds to the given entry path within the archive. The requested entry may or may not exist in the archive, the ProxyFile.exists() method of the returned entry file can be used used to get this information. However, if the requested entry does not exist in the archive and is not located at the top level (i.e. is located in a subfolder), its parent folder must exist in the archive or else an IOException will be thrown.

Important note: the given path's separator character must be '/' and the path must be relative to the archive's root, i.e. not start with a leading '/', otherwise the entry will not be found.

Parameters:
entryPath - path to an entry within this archive
Returns:
an AbstractFile that corresponds to the given entry path
Throws:
java.io.IOException - if neither the entry nor its parent exist within the archive

getEntries

public abstract java.util.Vector getEntries()
                                     throws java.io.IOException
Returns a Vector of ArchiveEntry, representing all the entries this archive file contains. This method will be called the first time one of the ls() is called. If will not be further called, unless the file's date has changed since the last time one of the ls() methods was called.

Throws:
java.io.IOException

getEntryInputStream

public abstract java.io.InputStream getEntryInputStream(ArchiveEntry entry)
                                                 throws java.io.IOException
Returns an InputStream to read from the given archive entry. The specified ArchiveEntry instance is necessarily one of the entries that were returned by getEntries().

Throws:
java.io.IOException

isWritableArchive

public abstract boolean isWritableArchive()
Returns true if this archive file is writable, i.e. is capable of adding and deleting entries to the underlying archive file.

This method is implemented by AbstractROArchiveFile and AbstractRWArchiveFile to respectively return false and true. This method may be overridden by AbstractRWArchiveFile implementations if write access is only available under certain conditions, for example if it requires random write access to the proxied archive file (which may not always be available). Therefore, this method should be used to test if an AbstractArchiveFile is writable, rather than testing if it is an instance of AbstractRWArchiveFile.

Returns:
true if this archive is writable, i.e. is capable of adding and deleting entries to the underlying archive file.

ls

public AbstractFile[] ls()
                  throws java.io.IOException
This method is overridden to list and return the topmost entries contained by this archive. The returned files are ArchiveEntryFile instances.

Overrides:
ls in class ProxyFile
Returns:
the topmost entries contained by this archive
Throws:
java.io.IOException - if the archive entries could not be listed

ls

public AbstractFile[] ls(FilenameFilter filter)
                  throws java.io.IOException
This method is overridden to list and return the topmost entries contained by this archive, filtering out the ones that do not match the specified FilenameFilter. The returned files are ArchiveEntryFile instances.

Overrides:
ls in class ProxyFile
Parameters:
filter - the FilenameFilter to be used to filter files out from the list, may be null
Returns:
the topmost entries contained by this archive
Throws:
java.io.IOException - if the archive entries could not be listed

ls

public AbstractFile[] ls(FileFilter filter)
                  throws java.io.IOException
This method is overridden to list and return the topmost entries contained by this archive, filtering out the ones that do not match the specified FileFilter. The returned files are ArchiveEntryFile instances.

Overrides:
ls in class ProxyFile
Parameters:
filter - the FilenameFilter to be used to filter files out from the list, may be null
Returns:
the topmost entries contained by this archive
Throws:
java.io.IOException - if the archive entries could not be listed

isBrowsable

public boolean isBrowsable()
Always returns true, archive files can be browsed even though they are not directories.

Overrides:
isBrowsable in class ProxyFile
Returns:
true if this file is browsable

isDirectory

public boolean isDirectory()
Always returns false, archive files can be browsed but they are not directiories.

Overrides:
isDirectory in class ProxyFile
Returns:
true if this file is a directory, false in any of the cases listed above

getFreeSpace

public long getFreeSpace()
Returns the proxied file's free space if this archive is writable (as reported by isWritableArchive(), else returns 0.

Overrides:
getFreeSpace in class ProxyFile
Returns:
the proxied file's free space is this archive is writable, 0 otherwise.

canRunProcess

public boolean canRunProcess()
Always returns false.

Overrides:
canRunProcess in class ProxyFile
Returns:
true if it's possible to run processes on the underlying file system, false otherwise.

runProcess

public AbstractProcess runProcess(java.lang.String[] tokens)
                           throws java.io.IOException
Always throws an IOException.

Overrides:
runProcess in class ProxyFile
Parameters:
tokens - command and its arguments for the process to create.
Returns:
a process executing the specified command tokens using this file as a working directory.
Throws:
java.io.IOException - thrown if an error occured while creating the process, if the current file is not a directory or if the operation is not supported.


This file is part of muCommander - Copyright (C) 2002-2008 Maxence Bernard