IMAPInputStreampublic class IMAPInputStream extends InputStream This class implements an IMAP data stream. |
Fields Summary |
---|
private IMAPMessage | msg | private String | section | private int | pos | private int | blksize | private int | max | private byte[] | buf | private int | bufcount | private int | bufpos | private boolean | peek | private ByteArray | readbuf | private static final int | slop |
Constructors Summary |
---|
public IMAPInputStream(IMAPMessage msg, String section, int max, boolean peek)Create an IMAPInputStream.
this.msg = msg;
this.section = section;
this.max = max;
this.peek = peek;
pos = 0;
blksize = msg.getFetchBlockSize();
|
Methods Summary |
---|
public synchronized int | available()Returns the number of bytes that can be read from this input
stream without blocking.
return (bufcount - bufpos);
| private void | checkSeen()Normally the SEEN flag will have been set by now, but if not,
force it to be set (as long as the folder isn't open read-only
and we're not peeking).
And of course, if there's no folder (e.g., a nested message)
don't do anything.
if (peek) // if we're peeking, don't set the SEEN flag
return;
try {
Folder f = msg.getFolder();
if (f != null && f.getMode() != Folder.READ_ONLY &&
!msg.isSet(Flags.Flag.SEEN))
msg.setFlag(Flags.Flag.SEEN, true);
} catch (MessagingException ex) {
// ignore it
}
| private void | fill()Fetch more data from the server. This method assumes that all
data has already been read in, hence bufpos > bufcount.
/*
* If we know the total number of bytes available from this
* section, let's check if we have consumed that many bytes.
*/
if (max != -1 && pos >= max) {
if (pos == 0)
checkSeen();
readbuf = null; // XXX - return to pool?
return; // the caller of fill() will return -1.
}
BODY b = null;
if (readbuf == null)
readbuf = new ByteArray(blksize + slop);
ByteArray ba;
// Acquire MessageCacheLock, to freeze seqnum.
synchronized (msg.getMessageCacheLock()) {
try {
IMAPProtocol p = msg.getProtocol();
// Check whether this message is expunged
if (msg.isExpunged())
throw new MessageRemovedIOException(
"No content for expunged message");
int seqnum = msg.getSequenceNumber();
int cnt = blksize;
if (max != -1 && pos + blksize > max)
cnt = max - pos;
if (peek)
b = p.peekBody(seqnum, section, pos, cnt, readbuf);
else
b = p.fetchBody(seqnum, section, pos, cnt, readbuf);
} catch (ProtocolException pex) {
forceCheckExpunged();
throw new IOException(pex.getMessage());
} catch (FolderClosedException fex) {
throw new FolderClosedIOException(fex.getFolder(),
fex.getMessage());
}
if (b == null || ((ba = b.getByteArray()) == null)) {
forceCheckExpunged();
throw new IOException("No content");
}
}
// make sure the SEEN flag is set after reading the first chunk
if (pos == 0)
checkSeen();
// setup new values ..
buf = ba.getBytes();
bufpos = ba.getStart();
int n = ba.getCount(); // will be zero, if all data has been
// consumed from the server.
bufcount = bufpos + n;
pos += n;
| private void | forceCheckExpunged()Do a NOOP to force any untagged EXPUNGE responses
and then check if this message is expunged.
synchronized (msg.getMessageCacheLock()) {
try {
msg.getProtocol().noop();
} catch (ConnectionException cex) {
throw new FolderClosedIOException(msg.getFolder(),
cex.getMessage());
} catch (FolderClosedException fex) {
throw new FolderClosedIOException(fex.getFolder(),
fex.getMessage());
} catch (ProtocolException pex) {
// ignore it
}
}
if (msg.isExpunged())
throw new MessageRemovedIOException();
| public synchronized int | read()Reads the next byte of data from this buffered input stream.
If no byte is available, the value -1 is returned.
if (bufpos >= bufcount) {
fill();
if (bufpos >= bufcount)
return -1; // EOF
}
return buf[bufpos++] & 0xff;
| public synchronized int | read(byte[] b, int off, int len)Reads up to len bytes of data from this
input stream into the given buffer.
Returns the total number of bytes read into the buffer,
or -1 if there is no more data.
Note that this method mimics the "weird !" semantics of
BufferedInputStream in that the number of bytes actually
returned may be less that the requested value. So callers
of this routine should be aware of this and must check
the return value to insure that they have obtained the
requisite number of bytes.
int avail = bufcount - bufpos;
if (avail <= 0) {
fill();
avail = bufcount - bufpos;
if (avail <= 0)
return -1; // EOF
}
int cnt = (avail < len) ? avail : len;
System.arraycopy(buf, bufpos, b, off, cnt);
bufpos += cnt;
return cnt;
| public int | read(byte[] b)Reads up to b.length bytes of data from this input
stream into an array of bytes.
Returns the total number of bytes read into the buffer, or
-1 is there is no more data.
Note that this method mimics the "weird !" semantics of
BufferedInputStream in that the number of bytes actually
returned may be less that the requested value. So callers
of this routine should be aware of this and must check
the return value to insure that they have obtained the
requisite number of bytes.
return read(b, 0, b.length);
|
|