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 public class DecodingContext {
38
39 private IoBuffer decodedBuffer;
40
41 private IoBuffer delimiter;
42
43 private int contentLength = -1;
44
45 private int matchCount = 0;
46
47 public void clean() {
48 contentLength = -1;
49 matchCount = 0;
50 decodedBuffer = null;
51 }
52
53 public int getContentLength() {
54 return contentLength;
55 }
56
57 public void setContentLength(int contentLength) {
58 this.contentLength = contentLength;
59 }
60
61 public int getMatchCount() {
62 return matchCount;
63 }
64
65 public void setMatchCount(int matchCount) {
66 this.matchCount = matchCount;
67 }
68
69 public IoBuffer getDecodedBuffer() {
70 return decodedBuffer;
71 }
72
73 public void setDecodedBuffer(IoBuffer decodedBuffer) {
74 this.decodedBuffer = decodedBuffer;
75 }
76
77 public IoBuffer getDelimiter() {
78 return delimiter;
79 }
80
81 public void setDelimiter(IoBuffer delimiter) {
82 this.delimiter = delimiter;
83 }
84 }
85
86 private DecodingContext ctx = new DecodingContext();
87
88
89
90
91
92 public IoBufferDecoder(byte[] delimiter) {
93 setDelimiter(delimiter, true);
94 }
95
96
97
98
99 public IoBufferDecoder(int contentLength) {
100 setContentLength(contentLength, false);
101 }
102
103
104
105
106
107
108
109 public void setContentLength(int contentLength, boolean resetMatchCount) {
110 if (contentLength <= 0) {
111 throw new IllegalArgumentException("contentLength: "
112 + contentLength);
113 }
114
115 ctx.setContentLength(contentLength);
116 if (resetMatchCount) {
117 ctx.setMatchCount(0);
118 }
119 }
120
121
122
123
124
125
126
127
128
129 public void setDelimiter(byte[] delim, boolean resetMatchCount) {
130 if (delim == null) {
131 throw new NullPointerException("Null delimiter not allowed");
132 }
133
134
135 IoBuffer delimiter = IoBuffer.allocate(delim.length);
136 delimiter.put(delim);
137 delimiter.flip();
138
139 ctx.setDelimiter(delimiter);
140 ctx.setContentLength(-1);
141 if (resetMatchCount) {
142 ctx.setMatchCount(0);
143 }
144 }
145
146
147
148
149
150
151
152 public IoBuffer decodeFully(IoBuffer in) {
153 int contentLength = ctx.getContentLength();
154 IoBuffer decodedBuffer = ctx.getDecodedBuffer();
155
156 int oldLimit = in.limit();
157
158
159 if (contentLength > -1) {
160 if (decodedBuffer == null) {
161 decodedBuffer = IoBuffer.allocate(contentLength).setAutoExpand(
162 true);
163 }
164
165 if (in.remaining() < contentLength) {
166 int readBytes = in.remaining();
167 decodedBuffer.put(in);
168 ctx.setDecodedBuffer(decodedBuffer);
169 ctx.setContentLength(contentLength - readBytes);
170 return null;
171
172 } else {
173 int newLimit = in.position() + contentLength;
174 in.limit(newLimit);
175 decodedBuffer.put(in);
176 decodedBuffer.flip();
177 in.limit(oldLimit);
178 ctx.clean();
179
180 return decodedBuffer;
181 }
182 }
183
184
185 int oldPos = in.position();
186 int matchCount = ctx.getMatchCount();
187 IoBuffer delimiter = ctx.getDelimiter();
188
189 while (in.hasRemaining()) {
190 byte b = in.get();
191 if (delimiter.get(matchCount) == b) {
192 matchCount++;
193 if (matchCount == delimiter.limit()) {
194
195 int pos = in.position();
196 in.position(oldPos);
197
198 in.limit(pos);
199
200 if (decodedBuffer == null) {
201 decodedBuffer = IoBuffer.allocate(in.remaining())
202 .setAutoExpand(true);
203 }
204
205 decodedBuffer.put(in);
206 decodedBuffer.flip();
207
208 in.limit(oldLimit);
209 ctx.clean();
210
211 return decodedBuffer;
212 }
213 } else {
214 in.position(Math.max(0, in.position() - matchCount));
215 matchCount = 0;
216 }
217 }
218
219
220 if (in.remaining() > 0) {
221 in.position(oldPos);
222 decodedBuffer.put(in);
223 in.position(in.limit());
224 }
225
226
227 ctx.setMatchCount(matchCount);
228 ctx.setDecodedBuffer(decodedBuffer);
229
230 return decodedBuffer;
231 }
232 }