Using the WrappedOutputStream and WrappedInputStream classes (from the
samples.socket.io package of Xerces) for the transport of XML documents between
a client and a server, we recently became aware of the following problem with
the WrappedOutputStream class:
It is currently only possible to send XML documents
whose byte[] representation doesn't exceed 65535 bytes
using the write(byte[] b,int offset,int length) method.
As I see it, this is caused by a combination of the particular method
implementation and the fact that the protocol used by these classes represents
the size of each byte[] "packet" by a short, i.e. 16 bits.
There are several ways one can fix/circumvent this problem of course, some of
which are:
1) Introduce a loop, and use WrappedOutputStream's write(int b) method instead
of the write(byte[] b, int offset, int length) method. The write(int b) method
buffers the bytes in an internal byte[] array which is 1024 bytes long (by
default), and sends a 1024 byte packet each time the buffer is filled up.
2) One could modify the write(byte[] b, int offset, int length) method so that
it chunks the byte[] argument into several smaller pieces, each less than 65535
bytes long, and sends these as separate packets.
3) One could modify the WrappedOutputStream/WrappedInputStream classes so that
they use a long (64 bits) instead of a short to represents the size of each
byte[] packet.
I tried approach 1) first, replacing
wrap_os.write(bytes, 0, bytes.length);
by
for(int i=0; i<bytes.length; i++) {
wrap_os.write(bytes[i]);
}
in my code, where wrap_os is a WrappedOutputStream object. This failed, and
revealed a bug in the write(int b) method in WrappedOutputStream:
[snippet from WrappedOutputStream.java]
/**
* Writes a single byte to the output.
* <p>
* <strong>Note:</strong> Single bytes written to the output stream
* will be buffered
*/
public void write(int b) throws IOException {
fBuffer[fPosition++] = (byte)b;
if (fPosition == fBuffer.length) {
fPosition = 0;
fDataOutputStream.writeShort(fBuffer.length); <-------
write(fBuffer, 0, fBuffer.length);
}
} // write(int)
/** Writes an array of bytes to the output. */
public void write(byte[] b, int offset, int length)
throws IOException {
// flush existing buffer
if (fPosition > 0) {
flush0();
}
// write header followed by actual bytes
fDataOutputStream.writeShort(length);
super.out.write(b, offset, length);
} // write(byte[])
When fBuffer is filled up, the size of the buffer is written as a short onto
the DataOutputStream, and then the fBuffer is written using the write(byte[] b,
int offset, int length) which also writes the size of the buffer onto the
DataOutputStream before writing the actual byte array. This makes the
WrappedInputStream object at the receiving end somewhat confused... This is
easily fixed by deleting the fDataOutputStream.writeShort(fBuffer.length); line
from the write(int b) method.
Anyhow, I guess I will have to do something along the lines of 2) or 3) above,
since the WrappedOutputStream class currently doesn't handle large byte[]
arrays as it seems. If anyone has experienced/dealt with the same problem, tips
and comments are of course greatly appreciated.
--
------------------------------------------------
Morten Bj�rhus
TBS Communications, Messaging and Mobility
[EMAIL PROTECTED], tel: +47 41660525
------------------------------------------------
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]