1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package net.sf.wallace.mina;
20
21 import java.io.StringReader;
22 import java.util.regex.Matcher;
23 import java.util.regex.Pattern;
24
25 import net.sf.wallace.ClientMessage;
26 import net.sf.wallace.ServerResponse;
27 import net.sf.wallace.antlr.IMAP4CommandLexer;
28 import net.sf.wallace.antlr.IMAP4CommandParser;
29
30 import org.apache.mina.common.ByteBuffer;
31 import org.apache.mina.protocol.ProtocolDecoder;
32 import org.apache.mina.protocol.ProtocolDecoderOutput;
33 import org.apache.mina.protocol.ProtocolSession;
34 import org.apache.mina.protocol.ProtocolViolationException;
35
36 import antlr.RecognitionException;
37 import antlr.TokenStreamException;
38
39 /***
40 * IMAP4 protocol decoder.
41 *
42 * TODO A command must be able to span multiple calls to decode().
43 *
44 * @author rnewson
45 */
46 public final class IMAP4ProtocolDecoder implements ProtocolDecoder {
47
48 private static final int AVERAGE_COMMAND_LENGTH = 100;
49
50 private static final Pattern LITERAL_PATTERN = Pattern.compile("//{(//d+)//+?//}\r\n$");
51
52 private StringBuffer stringBuffer = new StringBuffer(AVERAGE_COMMAND_LENGTH);
53
54 public void decode(final ProtocolSession protocolSession, final ByteBuffer buffer, final ProtocolDecoderOutput output)
55 throws ProtocolViolationException {
56 assert protocolSession != null : "protocolSession cannot be null.";
57
58 do {
59 final char c = (char) buffer.get();
60 stringBuffer.append(c);
61 } while (buffer.hasRemaining());
62
63 final Matcher m = LITERAL_PATTERN.matcher(stringBuffer);
64
65 if (m.find()) {
66 protocolSession.write(new ServerResponse(ServerResponse.Type.CONTINUATION, "Ready for " + m.group(1) + " bytes."));
67 return;
68 }
69
70 final String string = stringBuffer.toString();
71
72 try {
73 final IMAP4CommandLexer lexer = new IMAP4CommandLexer(new StringReader(string));
74 final IMAP4CommandParser parser = new IMAP4CommandParser(lexer);
75 final ClientMessage message = parser.command();
76 output.write(message);
77 } catch (RecognitionException e) {
78 throw new ProtocolViolationException("Failed to recognize '" + string + "'", e);
79 } catch (TokenStreamException e) {
80 throw new ProtocolViolationException(e);
81 } finally {
82 stringBuffer = new StringBuffer(AVERAGE_COMMAND_LENGTH);
83 }
84
85 }
86 }