Wednesday, 17 January 2007

Fetch Command & Evil Hacks

« Bustin' out the ANTLR-fu | Main | Panto 0.1 released »

I've just committed a working implementation of the FETCH command for our imap server, we were missing support for individual message body parts and doing partial fetches. I've had to redo some of our mime parser implementation in order to build our message & body parts correctly. We're currently using the Mime4J from the James mail server project. The implementation is quite solid and provides a nice SAX style model for hooking into the parser. It uses a byte by byte comparison to determine when it matches. It would be nice to improve this using something like Boyer-Moore to match the mime boundary.

I ran into a bit of a quirk with my implementation of the code that writes Mime message out to the user. I currently walk a the message tree structure, writing each part to an OutputStream. When implementing the partial fetch I noticed that would of had to check the number of bytes written at each point. The proper fix (which I will do at some point) would be to lazily create an InputStream so that the message structure can be "read". For the time being I have implemented a quick hack.

private static class SizeLimitedOutputStream 
    extends OutputStream {

    @Override
    public void write(byte[] b, int off, int len) throws IOException {
            
        if (pos >= end) {
            out.flush();
            throw LimitReachedException.instance();
        } else if (pos + len >= start) {
            int toSkip = Math.max(0, start - pos);
            int toTrunc = Math.max(0, (pos + len) - end);
            off += toSkip;
            len -= (toSkip + toTrunc);
            if (off < b.length) {
                out.write(b, off, len);
            }
            pos += (len + toSkip);
        } else {
            pos += len;
        }
    }

Basically throw the exception to signal that the size limit has been reached. Apparently the RIFE framework uses excecptions to implement continuations as I found in this entry in the Java Specialists' Newsletter which describes an approach to improve the preformance of exception creation.

private static class LimitReachedException extends RuntimeException {
    private final static LimitReachedException e 
        = new LimitReachedException();

    public Throwable fillInStackTrace() {
        return null;
    }
        
    public static LimitReachedException instance() {
        return e;
    }
}

A sufficently evil hack. I will have the proper fix in before 1.0 (which will be quicker as it will handle offsets more efficiently), but this will do prior to then.

Technorati Tags:

Posted by mbarker at 10:52 PM in Meldware

 

« January »
SunMonTueWedThuFriSat
 123456
78910111213
14151617181920
21222324252627
28293031