FileDocCategorySizeDatePackage
IMAPInputStream.javaAPI DocJavaMail 1.4.38664Tue Nov 17 10:38:10 GMT 2009com.sun.mail.imap

IMAPInputStream

public class IMAPInputStream extends InputStream
This class implements an IMAP data stream.
author
John Mani

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 intavailable()
Returns the number of bytes that can be read from this input stream without blocking.

	return (bufcount - bufpos);
    
private voidcheckSeen()
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 voidfill()
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 voidforceCheckExpunged()
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 intread()
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 intread(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 intread(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);