FileDocCategorySizeDatePackage
MessageInputStream.javaAPI DocApache James 2.3.17772Fri Jan 12 12:56:24 GMT 2007org.apache.james.mailrepository

MessageInputStream

public final class MessageInputStream extends InputStream
This class provides an inputStream for a Mail object. If the Mail is larger than 4KB it uses Piped streams and a worker threads Otherwise it simply create a temporary byte buffer and does not create the worker thread. Note: Javamail (or the Activation Framework) already uses a worker threads when asked for an inputstream.

Fields Summary
private long
size
The size of the current message
private InputStream
wrapped
The wrapped stream (Piped or Binary)
private Exception
caughtException
If an excaption happens in the worker threads it's stored here
private org.apache.avalon.cornerstone.services.store.StreamRepository
streamRep
Stream repository used for dbfiles (null otherwise)
Constructors Summary
public MessageInputStream(org.apache.mailet.Mail mc, org.apache.avalon.cornerstone.services.store.StreamRepository srep, int sizeLimit)
Main constructor. If srep is not null than we are using dbfiles and we stream the body to file and only the header to db.

    
                                  
              
        super();
        caughtException = null;
        streamRep = srep;
        size = mc.getMessageSize();
        // we use the pipes only when streamRep is null and the message size is greater than 4096
        // Otherwise we should calculate the header size and not the message size when streamRep is not null (JAMES-475)
        if (streamRep == null && size > sizeLimit) {
            PipedOutputStream headerOut = new PipedOutputStream();
            new Thread() {
                private Mail mail;

                private PipedOutputStream out;

                public void run() {
                    try {
                        writeStream(mail,out);
                    } catch (IOException e) {
                        caughtException = e;
                    } catch (MessagingException e) {
                        caughtException = e;
                    }
                }

                public Thread setParam(Mail mc, PipedOutputStream headerOut) {
                    this.mail = mc;
                    this.out = headerOut;
                    return this;
                }
            }.setParam(mc,(PipedOutputStream) headerOut).start();
            wrapped = new PipedInputStream(headerOut);
        } else {
            ByteArrayOutputStream headerOut = new ByteArrayOutputStream();
            writeStream(mc,headerOut);
            wrapped = new ByteArrayInputStream(headerOut.toByteArray());
            size = headerOut.size();
        }
    
Methods Summary
public intavailable()

see
java.io.InputStream#available()

        if (caughtException != null || wrapped == null) {
            throwException();
        }
        return wrapped.available();
    
public voidclose()

see
java.io.Closeable#close()

        if (caughtException != null || wrapped == null) {
            throwException();
        }
        wrapped.close();
        wrapped = null;
    
private voidcloseOutputStreams(java.io.OutputStream headerStream, java.io.OutputStream bodyStream)
Closes output streams used to update message

param
headerStream the stream containing header information - potentially the same as the body stream
param
bodyStream the stream containing body information
throws
IOException

        try {
            // If the header stream is not the same as the body stream,
            // close the header stream here.
            if ((headerStream != null) && (headerStream != bodyStream)) {
                headerStream.close();
            }
        } finally {
            if (bodyStream != null) {
                bodyStream.close();
            }
        }
    
public longgetSize()
Returns the size of the full message

        return size;
    
public synchronized voidmark(int arg0)

see
java.io.InputStream#mark(int)

        wrapped.mark(arg0);
    
public booleanmarkSupported()

see
java.io.InputStream#markSupported()

        return wrapped.markSupported();
    
public intread(byte[] arg0, int arg1, int arg2)

see
java.io.InputStream#read(byte[], int, int)

        if (caughtException != null || wrapped == null) {
            throwException();
        }
        return wrapped.read(arg0, arg1, arg2);
    
public intread(byte[] arg0)

see
java.io.InputStream#read(byte[])

        if (caughtException != null || wrapped == null) {
            throwException();
        }
        return wrapped.read(arg0);
    
public intread()

see
java.io.InputStream#read()

        if (caughtException != null || wrapped == null) {
            throwException();
        }
        return wrapped.read();
    
public synchronized voidreset()

see
java.io.InputStream#reset()

        if (caughtException != null || wrapped == null) {
            throwException();
        }
        wrapped.reset();
    
public longskip(long arg0)

see
java.io.InputStream#skip(long)

        if (caughtException != null || wrapped == null) {
            throwException();
        }
        return wrapped.skip(arg0);
    
private voidthrowException()

        try {
            if (wrapped == null) {
                throw new IOException("wrapped stream does not exists anymore");
            } else if (caughtException instanceof IOException) {
                throw (IOException) caughtException;
            } else {
                throw new IOException("Exception caugth in worker thread "+caughtException.getMessage()) {
                    /**
                     * @see java.lang.Throwable#getCause()
                     */
                    public Throwable getCause() {
                        return caughtException;
                    }
                };
            }
        } finally {
            caughtException = null;
            wrapped = null;
        }
    
private voidwriteStream(org.apache.mailet.Mail mail, java.io.OutputStream out)
write the full mail to the stream This can be used by this object or by the worker threads.

        OutputStream bodyOut = null;
        try {
            if (streamRep == null) {
                //If there is no filestore, use the byte array to store headers
                //  and the body
                bodyOut = out;
            } else {
                //Store the body in the stream repository
                bodyOut = streamRep.put(mail.getName());
            }
        
            //Write the message to the headerOut and bodyOut.  bodyOut goes straight to the file
            MimeMessageUtil.writeTo(mail.getMessage(), out, bodyOut);
            out.flush();
            bodyOut.flush();
        
        } finally {
            closeOutputStreams(out, bodyOut);
        }