Rather than try to support mixing Avian's core classes with those of
an external class library -- which necessitates adding a lot of stub
methods which throw UnsupportedOperationExceptions, among other
comprimises -- we're looking to support such external class libraries
in their unmodified forms. The latter strategy has already proven
successful with OpenJDK's class library. Thus, this commit removes
the stub methods, etc., which not only cleans up the code but avoids
misleading application developers as to what classes and methods
Avian's built-in class library supports.
We were incorrectly returning an empty array when the input was empty,
whereas we ought to return an array containing a single empty string.
When the pattern to match was empty, we went into a loop to create an
infinite list of empty strings, only to crash once we've run out of
memory. This commit addresses both problems.
In order to facilitate making the VM compatible with multiple class
libraries, it's useful to separate the VM-specific representation of
these classes from the library implementations. This commit
introduces VMClass, VMField, and VMMethod for that purpose.
Note the following excerpt from PNGFileFormat.java in SWT:
/*
* InflaterInputStream does not consume all bytes in the stream
* when it is closed. This may leave unread IDAT chunks. The fix
* is to read all available bytes before closing it.
*/
while (stream.available() > 0) stream.read();
stream.close();
This code relies on the documented behavior of
InflaterInputStream.available, which must return "0 after EOF has been
reached, otherwise always return 1". This is unlike
InputStream.available, which is documented to return "the number of
bytes that can be read (or skipped over) from this input stream
without blocking by the next caller of a method for this input
stream", and says nothing about how many bytes are left until the end
of stream.
This commit modifies InflaterInputStream.available to behave according
to Sun's documentation.
We now maintain a virtual root loger, on which you can set the log
level. When any logger logs, it finds the effective log level by going
up the parent chain, and finding a meaningful log lvel. Thus, one can
now do Logger.getLogger("").setLevel(Level.FINER) and set the log level
for all other loggers (that do not specify their own default) to the
level specified.