BoundaryDelimitedStreampublic class BoundaryDelimitedStream extends FilterInputStream This class takes the input stream and turns it multiple streams. |
Fields Summary |
---|
protected static Log | logThe Log that this class should log all events to. | protected byte[] | boundary | int | boundaryLenThe boundary length. | int | boundaryBufLenThe boundary length plus crlf. | InputStream | isThe source input stream. | boolean | closedThe stream has been closed. | boolean | eoseof has been detected. | boolean | theEndThere are no more streams left. | int | readbufszMinimum to read at one time. | byte[] | readbufThe buffer we are reading. | int | readBufPosWhere we have read so far in the stream. | int | readBufEndThe number of bytes in array. | protected static final int | BOUNDARY_NOT_FOUNDField BOUNDARY_NOT_FOUND. | int | boundaryPosField boundaryPos. | static int | streamCountThe number of streams produced. | protected int | streamNoField streamNo. | static boolean | isDebugEnabledField isDebugEnabled. | private int[] | skip |
Constructors Summary |
---|
protected BoundaryDelimitedStream(BoundaryDelimitedStream prev, int readbufsz)Constructor to create the next stream from the previous one.
super(null);
streamNo = newStreamNo();
boundary = prev.boundary;
boundaryLen = prev.boundaryLen;
boundaryBufLen = prev.boundaryBufLen;
skip = prev.skip;
is = prev.is;
closed = false; // The new one is not closed.
eos = false; // Its not at th EOS.
readbufsz = prev.readbufsz;
readbuf = prev.readbuf;
// Move past the old boundary.
readBufPos = prev.readBufPos + boundaryBufLen;
readBufEnd = prev.readBufEnd;
// find the new boundary.
boundaryPos = boundaryPosition(readbuf, readBufPos, readBufEnd);
prev.theEnd = theEnd; // The stream.
| BoundaryDelimitedStream(InputStream is, byte[] boundary, int readbufsz)Create a new boundary stream.
// super (is);
super(null); // we handle everything so this is not necessary, don't won't to hang on to a reference.
isDebugEnabled = log.isDebugEnabled();
streamNo = newStreamNo();
closed = false;
this.is = is;
// Copy the boundary array to make certain it is never altered.
this.boundary = new byte[boundary.length];
System.arraycopy(boundary, 0, this.boundary, 0, boundary.length);
this.boundaryLen = this.boundary.length;
this.boundaryBufLen = boundaryLen + 2;
// allways leave room for at least a 2x boundary
// Most mime boundaries are 40 bytes or so.
this.readbufsz = Math.max((boundaryBufLen) * 2, readbufsz);
|
Methods Summary |
---|
public int | available()
int bcopy = readBufEnd - readBufPos - boundaryBufLen;
// never go past the boundary.
bcopy = Math.min(bcopy, boundaryPos - readBufPos);
return Math.max(0, bcopy);
| protected int | boundaryPosition(byte[] searchbuf, int start, int end)Read from the boundary delimited stream.
int foundAt = boundarySearch(searchbuf, start, end);
// First find the boundary marker
if (BOUNDARY_NOT_FOUND != foundAt) { // Something was found.
if (foundAt + boundaryLen + 2 > end) {
foundAt = BOUNDARY_NOT_FOUND;
} else {
// If the marker has a "--" at the end then this is the last boundary.
if ((searchbuf[foundAt + boundaryLen] == '-")
&& (searchbuf[foundAt + boundaryLen + 1] == '-")) {
finalClose();
} else if ((searchbuf[foundAt + boundaryLen] != 13)
|| (searchbuf[foundAt + boundaryLen + 1] != 10)) {
// If there really was no crlf at then end then this is not a boundary.
foundAt = BOUNDARY_NOT_FOUND;
}
}
}
return foundAt;
| private int | boundarySearch(byte[] text, int start, int end)
// log.debug(">>>>" + start + "," + end);
int i = 0, j = 0, k = 0;
if (boundaryLen > (end - start)) {
return BOUNDARY_NOT_FOUND;
}
if (null == skip) {
skip = new int[256];
java.util.Arrays.fill(skip, boundaryLen);
for (k = 0; k < boundaryLen - 1; k++) {
skip[boundary[k]] = boundaryLen - k - 1;
}
}
for (k = start + boundaryLen - 1; k < end;
k += skip[text[k] & (0xff)]) {
// log.debug(">>>>" + k);
// printarry(text, k-boundaryLen+1, end);
try {
for (j = boundaryLen - 1, i = k;
(j >= 0) && (text[i] == boundary[j]); j--) {
i--;
}
} catch (ArrayIndexOutOfBoundsException e) {
StringBuffer sb = new StringBuffer();
sb.append(
">>>"
+ e); // rr temporary till a boundary issue is resolved.
sb.append("start=" + start);
sb.append("k=" + k);
sb.append("text.length=" + text.length);
sb.append("i=" + i);
sb.append("boundary.length=" + boundary.length);
sb.append("j=" + j);
sb.append("end=" + end);
log.warn(Messages.getMessage("exception01",sb.toString()));
throw e;
}
if (j == (-1)) {
return i + 1;
}
}
// log.debug(">>>> not found" );
return BOUNDARY_NOT_FOUND;
| public synchronized void | close()Closes the stream.
if (closed) {
return;
}
log.debug(Messages.getMessage("bStreamClosed", "" + streamNo));
closed = true; // mark it closed.
if (!eos) { // We need get this off the stream.
// Easy way to flush through the stream;
byte[] readrest = new byte[1024 * 16];
int bread = 0;
do {
bread = read(readrest);
} while (bread > -1);
}
| protected void | finalClose()Close the underlying stream and remove all references to it.
if(theEnd) return;
theEnd= true;
is.close();
is= null;
| public synchronized org.apache.axis.attachments.BoundaryDelimitedStream | getNextStream()Gets the next stream. From the previous using the same buffer size to
read.
return getNextStream(readbufsz);
| protected synchronized org.apache.axis.attachments.BoundaryDelimitedStream | getNextStream(int readbufsz)Gets the next stream. From the previous using new buffer reading size.
BoundaryDelimitedStream ret = null;
if (!theEnd) {
// Create an new boundary stream that comes after this one.
ret = new BoundaryDelimitedStream(this, readbufsz);
}
return ret;
| public void | mark(int readlimit)mark the stream.
This is not supported.
// do nothing
| public boolean | markSupported()markSupported
return false;
return false;
| protected static synchronized int | newStreamNo()Signal that a new stream has been created.
log.debug(Messages.getMessage("streamNo", "" + (streamCount + 1)));
return ++streamCount;
| public static void | printarry(byte[] b, int start, int end)Method printarry
if (log.isDebugEnabled()) {
byte tb[] = new byte[end - start];
System.arraycopy(b, start, tb, 0, end - start);
log.debug("\"" + new String(tb) + "\"");
}
| public int | read()Read from the boundary delimited stream.
byte[] b = new byte[1]; // quick and dirty. //for now
int read = read(b);
if (read < 0) {
return -1;
} else {
return b[0]&0xff;
}
| public synchronized int | read(byte[] b, int off, int len)Read from the boundary delimited stream.
if (closed) {
throw new java.io.IOException(Messages.getMessage("streamClosed"));
}
if (eos) {
return -1;
}
if (readbuf == null) { // Allocate the buffer.
readbuf = new byte[Math.max(len, readbufsz)];
readBufEnd = readFromStream(readbuf);
if (readBufEnd < 0) {
readbuf = null;
closed = true;
finalClose();
throw new java.io.IOException(
Messages.getMessage("eosBeforeMarker"));
}
readBufPos = 0;
// Finds the boundary pos.
boundaryPos = boundaryPosition(readbuf, 0, readBufEnd);
}
int bwritten = 0; // Number of bytes written.
// read and copy bytes in.
do { // Always allow to have a boundary length left in the buffer.
int bcopy = Math.min(readBufEnd - readBufPos - boundaryBufLen,
len - bwritten);
// never go past the boundary.
bcopy = Math.min(bcopy, boundaryPos - readBufPos);
if (bcopy > 0) {
System.arraycopy(readbuf, readBufPos, b, off + bwritten, bcopy);
bwritten += bcopy;
readBufPos += bcopy;
}
if (readBufPos == boundaryPos) {
eos = true; // hit the boundary so it the end of the stream.
log.debug(Messages.getMessage("atEOS", "" + streamNo));
} else if (bwritten < len) { // need to get more data.
byte[] dstbuf = readbuf;
if (readbuf.length < len) {
dstbuf = new byte[len];
}
int movecnt = readBufEnd - readBufPos;
// copy what was left over.
System.arraycopy(readbuf, readBufPos, dstbuf, 0, movecnt);
// Read in the new data.
int readcnt = readFromStream(dstbuf, movecnt,
dstbuf.length - movecnt);
if (readcnt < 0) {
readbuf = null;
closed = true;
finalClose();
throw new java.io.IOException(
Messages.getMessage("eosBeforeMarker"));
}
readBufEnd = readcnt + movecnt;
readbuf = dstbuf;
readBufPos = 0; // start at the begining.
// just move the boundary by what we moved
if (BOUNDARY_NOT_FOUND != boundaryPos) {
boundaryPos -= movecnt;
} else {
boundaryPos = boundaryPosition(
readbuf, readBufPos,
readBufEnd); // See if the boundary is now there.
}
}
}
// read till we get the amount or the stream is finished.
while (!eos && (bwritten < len));
if (log.isDebugEnabled()) {
if (bwritten > 0) {
byte tb[] = new byte[bwritten];
System.arraycopy(b, off, tb, 0, bwritten);
log.debug(Messages.getMessage("readBStream",
new String[]{"" + bwritten,
"" + streamNo,
new String(tb)}));
}
}
if (eos && theEnd) {
readbuf = null; // dealloc even in Java.
}
return bwritten;
| public int | read(byte[] b)Read from the boundary delimited stream.
return read(b, 0, b.length);
| private final int | readFromStream(byte[] b)
return readFromStream(b, 0, b.length);
| private final int | readFromStream(byte[] b, int start, int length)
int minRead = Math.max(boundaryBufLen * 2, length);
minRead = Math.min(minRead, length - start);
int br = 0;
int brTotal = 0;
do {
br = is.read(b, brTotal + start, length - brTotal);
if (br > 0) {
brTotal += br;
}
} while ((br > -1) && (brTotal < minRead));
return (brTotal != 0)
? brTotal
: br;
| public void | reset()reset the stream.
This is not supported.
throw new java.io.IOException(
Messages.getMessage("attach.bounday.mns"));
|
|