This is a simple implementation of the OfferDatabase interface that
provides persistent storage for service offers.  All of the service
offers for a particular service type are stored in a single file.
A problem arose regarding how to name these files.  The first version
used the name of the service type (plus an extension) as the filename.
However, this strategy fails in the context of "complex" service type
names (e.g. '::One::Two'), which may use characters that are illegal
on some platforms.

Therefore, a mapping is maintained that associates a service type name
with a unique integer.  This mapping is stored in the file "offeridx.dat".
The resulting filenames are more cryptic (e.g. "OFR_23.dat"), but there's
no danger of using illegal characters.

The design decision to place all service offers for a service type
in a single file can lead to scalability issues, as every time the set
of offers for a service type changes, all of those offers must be written
back to the file.  Another alternative is to store each offer in its
own file, which makes adding and modifying offers efficient, but slows
down the process of reading the entire set of offers.

Serializable objects are used to maintain the persistent state of the
service offer database.  All of the classes except OfferDatabaseImpl
are serializable.  As such, they each have serialVersionUID variables
defined, which MUST be updated if the persistent representation of the
class changes (i.e. member data is added or removed).

Note that once an offer list (the set of offers for a service type)
has been loaded from its file, it is cached in memory from that point
on.  This makes subsequent lookups quite efficient, but may lead to
significant memory usage for higher-volume traders.
