E
- the Exception
class to throw by work(java.lang.String[])
and
run(java.lang.String[])
.public abstract class TApplication<E extends Exception> extends Object
setup()
phase and one or
more iterations of the work(java.lang.String[])
and finally sync()
phases.
Subclass or copy-and-edit the source code of this template class to meet your requirements.
Constructor and Description |
---|
TApplication() |
Modifier and Type | Method and Description |
---|---|
protected int |
run(String[] args)
Runs the setup-work-sync life cycle.
|
protected void |
setup()
Runs the setup phase.
|
protected void |
sync()
Runs the sync phase.
|
protected abstract int |
work(String[] args)
Runs the work phase.
|
protected final int run(String[] args) throws E extends Exception, FsSyncException
setup()
.
Then, a loop is entered which calls work(java.lang.String[])
and (in a finally
block) sync()
.
If work(java.lang.String[])
returns a negative integer, then the loop is
repeated.
Otherwise, the return value is used as the
exit status
of the VM.
Note that calling sync()
in a finally-block ensures that all
unsynchronized changes to the contents of all federated file systems
(i.e. archive files) get committed to their respective parent file
system, even if work(java.lang.String[])
throws an exception.
args
- an array of arguments for this application.E
- At the discretion of the work(java.lang.String[])
method.FsSyncException
- At the discretion of the sync()
method.E extends Exception
protected void setup()
This method is called by run(java.lang.String[])
at the start of the life cycle.
Its task is to configure the default behavior of the TrueVFS Access File* API
in order to answer the following questions:
Note that the method body of the implementation in the class
TApplication
is empty!
This means that the initial setup is not changed.
The initial setup is determined by loading service classes from the
classpath and applying reasonable defaults if nothing is found.
As an alternative to overriding this method, the setup may get changed
in a sub class constructor.
This would ensure it's changed exactly only once and not on every call
to run(java.lang.String[])
.
As the most simple use case, a client application might want to filter the initial setup for the archive file extensions it wants to detect. This is done as follows:
TConfig.get().setArchiveDetector(new TArchiveDetector("ear|jar|war"));
This will filter all file system drivers found on the classpath in the
initial setup so that only files with the pattern *.ear
,
*.jar
or *.war
(case ignoring) are detected
as prospective archive files.
If no file system driver is present for a named extension in the initial
setup, an IllegalArgumentException
is thrown.
The constructors of the TFile
class use the
TArchiveDetector
class to scan a path name for extensions of
archive files which shall be treated like virtual directories.
You can either explicitly inject this ArchiveDetector dependency into a
TFile constructor or you can rely on the value of the class property
defaultArchiveDetector
.
By default, all new TFile
objects will use a default
TArchiveDetector
which recognizes the canonical archive file
extensions registered by all archive driver modules which are present on
the runtime classpath.
However, if you use the following statement, all TFile
objects
will use the given default TArchiveDetector
which recognizes
only the given canonical file extensions for TAR, TAR.GZ, TAR.BZ2 and
ZIP files as archive files and hence as virtual directories.
This requires the JARs for the archive driver modules
truevfs-driver-tar
and truevfs-driver-zip
to be present
on the compile-time classpath:
TConfig.get().setArchiveDetector(
new TArchiveDetector(
TArchiveDetector.NULL,
new Object[][] {
{ "tar", new TarDriver(IOPoolLocator.SINGLETON) },
{ "tgz|tar.gz", new TarGZipDriver(IOPoolLocator.SINGLETON) },
{ "tbz|tb2|tar.bz2", new TarBZip2Driver(IOPoolLocator.SINGLETON) },
{ "zip", new ZipDriver(IOPoolLocator.SINGLETON)},
}));
Another typical use case is to recognize only Java artifacts.
TConfig.get().setArchiveDetector(
new TArchiveDetector(
"ear|jar|war",
new JarDriver(IOPoolLocator.SINGLETON)));
... or an application file format.
TConfig.get().setArchiveDetector(
new TArchiveDetector(
"foo",
new JarDriver(IOPoolLocator.SINGLETON)));
... or an encrypted application file format. This driver authenticates input archive files up to 512 KB using the Message Authentication Code (MAC) specified by the RAES file format. For larger input archive files, it just checks the CRC-32 value whenever an archive entry input stream is closed. CRC-32 has frequent collisions when compared to a MAC. However, it should not be feasible to make an undetectable modification. The driver also uses unencrypted temporary files for archive entries whenever required.
TConfig.get().setArchiveDetector(
new TArchiveDetector(
"bar",
new SafeZipRaesDriver(IOPoolLocator.SINGLETON)));
If you're a bit paranoid, then you could use the following driver instead: This driver authenticates every input archive file using the Message Authentication Code (MAC) specified by the RAES file format, which makes it comparably slow. The driver also uses unencrypted temporary files for archive entries whenever required.
TConfig.get().setArchiveDetector(
new TArchiveDetector(
"bar",
new ParanoidZipRaesDriver(IOPoolLocator.SINGLETON)));
And finally, if you're quite paranoid, then this driver is for you: This driver authenticates every input archive file using the Message Authentication Code (MAC) specified by the RAES file format, which makes it comparably slow. The driver also uses unencrypted byte arrays for temporary storage of archive entries whenever required. If you were completely paranoid, you would even want to use encrypted byte arrays or wipe them with nulls after use. However, then you would have to write this yourself! ;-)
TConfig.get().setArchiveDetector(
new TArchiveDetector(
"bar",
new ParanoidZipRaesDriver(new ByteArrayIOPoolService(2048))));
Last but not least, the following class property controls whether
archive files and their member directories get automatically created
whenever required.
The default value of this class property is true
!
TConfig.get().setLenient(false);
protected void sync() throws FsSyncException
This method is called by run(java.lang.String[])
in a finally-block after each call
to work(java.lang.String[])
.
Its task is to commit any unsynchronized changes to the contents of
archive files and purge all cached data so that third parties can safely
interact with these archive files until the next access by this TrueVFS
application.
The implementation in the class TApplication
simply calls
TVFS.umount()
.
FsSyncWarningException
- if only warning conditions
occur.
This implies that the respective parent file system has been
updated with constraints, such as a failure to set the last
modification time of the entry for the federated file system
(i.e. archive file) in its parent file system.FsSyncException
- if any error conditions occur.
This implies loss of data!protected abstract int work(String[] args) throws E extends Exception
This method is called by run(java.lang.String[])
at least once and repeatedly
called until it returns a non-negative integer for use as the
exist status
of the VM.
After this method, the sync()
method is called in a finally-block.
Avoid repeating this method and updating the same archive file upon each call! This would degrade the overall performance from O(n) to O(m*n), where m is the number of new or modified entries and n is the number of all entries in the archive file!
args
- an array of arguments for this application.exit status
of the VM.E
- At the discretion of the implementation.E extends Exception
Copyright © 2005–2018 Schlichtherle IT Services. All rights reserved.