1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package net.sf.beep4j.internal.message;
17
18 import java.nio.ByteBuffer;
19 import java.nio.CharBuffer;
20 import java.nio.charset.Charset;
21 import java.util.BitSet;
22
23 import net.sf.beep4j.Message;
24
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
27
28 public class DefaultMessageParser implements MessageParser {
29
30 private static final Logger LOG = LoggerFactory.getLogger(MessageParser.class);
31
32 private static final BitSet fieldChars;
33
34 static {
35 fieldChars = new BitSet();
36 for (int i = 0x21; i <= 0x39; i++) {
37 fieldChars.set(i);
38 }
39 for (int i = 0x3b; i <= 0x7e; i++) {
40 fieldChars.set(i);
41 }
42 }
43
44 public Message parse(ByteBuffer buffer) {
45 buffer.mark();
46 int pos = 0;
47 byte prev = 0;
48 boolean armed = true;
49 while (buffer.hasRemaining()) {
50 byte current = buffer.get();
51 if (prev == (byte) '\r' && current == (byte) '\n') {
52 if (armed) {
53 pos = buffer.position();
54 break;
55 }
56 armed = true;
57 } else if (current != '\r') {
58 armed = false;
59 }
60 prev = current;
61 }
62
63 LOG.debug("message body starts at offset " + buffer.position());
64
65 ByteBuffer content = buffer.slice();
66
67 buffer.reset();
68 buffer.limit(pos);
69
70 MessageHeader header = parseHeader(buffer);
71
72 return new DefaultMessage(header, content);
73 }
74
75 private MessageHeader parseHeader(ByteBuffer buffer) {
76 StringBuffer sb = new StringBuffer();
77
78 Charset charset = Charset.forName("US-ASCII");
79 CharBuffer chars = charset.decode(buffer);
80 sb.append(chars);
81
82 int start = 0;
83 int pos = 0;
84
85 MessageHeader header = new MessageHeader();
86
87 while (pos < sb.length()) {
88 while (pos < sb.length() && sb.charAt(pos) != '\r') {
89 pos++;
90 }
91 if (pos < sb.length() - 1 && sb.charAt(pos + 1) != '\n') {
92 pos++;
93 continue;
94 }
95
96 if (pos >= sb.length() - 2 || fieldChars.get(sb.charAt(pos + 2))) {
97
98
99
100
101
102 String field = sb.substring(start, pos);
103 start = pos + 2;
104
105
106
107
108 int index = field.indexOf(':');
109 boolean valid = false;
110 if (index != -1 && fieldChars.get(field.charAt(0))) {
111 valid = true;
112 String fieldName = field.substring(0, index).trim();
113 for (int i = 0; i < fieldName.length(); i++) {
114 if (!fieldChars.get(fieldName.charAt(i))) {
115 valid = false;
116 break;
117 }
118 }
119
120 if (valid) {
121 header.addHeader(fieldName, field.substring(index + 1));
122 }
123 }
124 }
125
126 pos += 2;
127 }
128
129 return header;
130 }
131
132 }