1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.mina.proxy.utils;
21
22 import org.apache.mina.core.buffer.IoBuffer;
23 import org.apache.mina.core.session.IoSession;
24 import org.apache.mina.filter.codec.textline.LineDelimiter;
25
26
27
28
29
30
31
32
33
34
35 public class IoBufferDecoder {
36
37
38
39
40 public class DecodingContext {
41
42
43
44
45 private IoBuffer decodedBuffer;
46
47
48
49
50 private IoBuffer delimiter;
51
52
53
54
55 private int matchCount = 0;
56
57
58
59
60
61 private int contentLength = -1;
62
63
64
65
66 public void reset() {
67 contentLength = -1;
68 matchCount = 0;
69 decodedBuffer = null;
70 }
71
72 public int getContentLength() {
73 return contentLength;
74 }
75
76 public void setContentLength(int contentLength) {
77 this.contentLength = contentLength;
78 }
79
80 public int getMatchCount() {
81 return matchCount;
82 }
83
84 public void setMatchCount(int matchCount) {
85 this.matchCount = matchCount;
86 }
87
88 public IoBuffer getDecodedBuffer() {
89 return decodedBuffer;
90 }
91
92 public void setDecodedBuffer(IoBuffer decodedBuffer) {
93 this.decodedBuffer = decodedBuffer;
94 }
95
96 public IoBuffer getDelimiter() {
97 return delimiter;
98 }
99
100 public void setDelimiter(IoBuffer delimiter) {
101 this.delimiter = delimiter;
102 }
103 }
104
105
106
107
108 private DecodingContext ctx = new DecodingContext();
109
110
111
112
113
114
115
116 public IoBufferDecoder(byte[] delimiter) {
117 setDelimiter(delimiter, true);
118 }
119
120
121
122
123
124
125 public IoBufferDecoder(int contentLength) {
126 setContentLength(contentLength, false);
127 }
128
129
130
131
132
133
134
135
136
137
138 public void setContentLength(int contentLength, boolean resetMatchCount) {
139 if (contentLength <= 0) {
140 throw new IllegalArgumentException("contentLength: " + contentLength);
141 }
142
143 ctx.setContentLength(contentLength);
144 if (resetMatchCount) {
145 ctx.setMatchCount(0);
146 }
147 }
148
149
150
151
152
153
154
155
156
157
158
159
160 public void setDelimiter(byte[] delim, boolean resetMatchCount) {
161 if (delim == null) {
162 throw new IllegalArgumentException("Null delimiter not allowed");
163 }
164
165
166 IoBuffer delimiter = IoBuffer.allocate(delim.length);
167 delimiter.put(delim);
168 delimiter.flip();
169
170 ctx.setDelimiter(delimiter);
171 ctx.setContentLength(-1);
172 if (resetMatchCount) {
173 ctx.setMatchCount(0);
174 }
175 }
176
177
178
179
180
181
182
183
184
185 public IoBuffer decodeFully(IoBuffer in) {
186 int contentLength = ctx.getContentLength();
187 IoBuffer decodedBuffer = ctx.getDecodedBuffer();
188
189 int oldLimit = in.limit();
190
191
192 if (contentLength > -1) {
193 if (decodedBuffer == null) {
194 decodedBuffer = IoBuffer.allocate(contentLength).setAutoExpand(true);
195 }
196
197
198 if (in.remaining() < contentLength) {
199 int readBytes = in.remaining();
200 decodedBuffer.put(in);
201 ctx.setDecodedBuffer(decodedBuffer);
202 ctx.setContentLength(contentLength - readBytes);
203 return null;
204
205 }
206
207 int newLimit = in.position() + contentLength;
208 in.limit(newLimit);
209 decodedBuffer.put(in);
210 decodedBuffer.flip();
211 in.limit(oldLimit);
212 ctx.reset();
213
214 return decodedBuffer;
215 }
216
217
218 int oldPos = in.position();
219 int matchCount = ctx.getMatchCount();
220 IoBuffer delimiter = ctx.getDelimiter();
221
222 while (in.hasRemaining()) {
223 byte b = in.get();
224 if (delimiter.get(matchCount) == b) {
225 matchCount++;
226 if (matchCount == delimiter.limit()) {
227
228 int pos = in.position();
229 in.position(oldPos);
230
231 in.limit(pos);
232
233 if (decodedBuffer == null) {
234 decodedBuffer = IoBuffer.allocate(in.remaining()).setAutoExpand(true);
235 }
236
237 decodedBuffer.put(in);
238 decodedBuffer.flip();
239
240 in.limit(oldLimit);
241 ctx.reset();
242
243 return decodedBuffer;
244 }
245 } else {
246 in.position(Math.max(0, in.position() - matchCount));
247 matchCount = 0;
248 }
249 }
250
251
252 if (in.remaining() > 0) {
253 in.position(oldPos);
254 decodedBuffer.put(in);
255 in.position(in.limit());
256 }
257
258
259 ctx.setMatchCount(matchCount);
260 ctx.setDecodedBuffer(decodedBuffer);
261
262 return decodedBuffer;
263 }
264 }