1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.geronimo.javamail.store.imap.connection;
19
20 import java.io.ByteArrayOutputStream;
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.util.ArrayList;
24 import java.util.HashMap;
25 import java.util.Map;
26
27 import javax.mail.MessagingException;
28 import javax.mail.event.FolderEvent;
29
30 import org.apache.geronimo.javamail.store.imap.connection.IMAPResponseTokenizer.Token;
31 import org.apache.geronimo.javamail.util.ConnectionException;
32
33 public class IMAPResponseStream {
34 protected final int BUFFER_SIZE = 1024;
35
36
37 protected InputStream in;
38
39 IMAPResponseBuffer out;
40
41 protected byte[] buffer = new byte[BUFFER_SIZE];
42
43 int position;
44
45 int length;
46
47 public IMAPResponseStream(InputStream in) {
48 this.in = in;
49 out = new IMAPResponseBuffer();
50 }
51
52 public int read() throws IOException {
53
54 if (!fillBufferIfNeeded()) {
55 return -1;
56 }
57
58 return buffer[position++];
59 }
60
61 protected boolean fillBufferIfNeeded() throws IOException {
62
63 if (position >= length) {
64 int readLength = 0;
65
66
67 while (readLength == 0) {
68 readLength = in.read(buffer, 0, buffer.length);
69 }
70
71 if (readLength == -1) {
72 return false;
73 }
74
75 position = 0;
76 length = readLength;
77 }
78 return true;
79 }
80
81
82
83
84
85
86
87
88
89 public IMAPResponse readResponse() throws MessagingException
90 {
91
92 out.reset();
93
94 byte[] data = readData();
95
96
97 IMAPResponseTokenizer tokenizer = new IMAPResponseTokenizer(data);
98
99 Token token = tokenizer.next();
100
101 int type = token.getType();
102
103
104 if (type == Token.CONTINUATION) {
105 return new IMAPContinuationResponse(data);
106 }
107
108
109 else if (type == Token.UNTAGGED) {
110
111 token = tokenizer.next();
112
113
114 if (token.isType(Token.NUMERIC)) {
115 int size = token.getInteger();
116
117 token = tokenizer.next();
118
119 String keyword = token.getValue();
120
121
122
123 if (keyword.equals("FETCH")) {
124 return new IMAPFetchResponse(size, data, tokenizer);
125 }
126 return new IMAPSizeResponse(keyword, size, data);
127 }
128
129
130
131
132 if (token.getType() != Token.ATOM) {
133 throw new MessagingException("Unknown server response: " + new String(data));
134 }
135
136 String keyword = token.getValue();
137
138 if (keyword.equals("OK")) {
139 return parseUntaggedOkResponse(data, tokenizer);
140 }
141
142 else if (keyword.equals("PREAUTH")) {
143 return new IMAPServerStatusResponse("PREAUTH", tokenizer.getRemainder(), data);
144 }
145
146 else if (keyword.equals("BYE")) {
147 return new IMAPServerStatusResponse("BYE", tokenizer.getRemainder(), data);
148 }
149 else if (keyword.equals("BAD")) {
150
151 return new IMAPServerStatusResponse("BAD", tokenizer.getRemainder(), data);
152 }
153 else if (keyword.equals("NO")) {
154
155 return new IMAPServerStatusResponse("NO", tokenizer.getRemainder(), data);
156 }
157
158 else if (keyword.equals("CAPABILITY")) {
159 return new IMAPCapabilityResponse(tokenizer, data);
160 }
161
162 else if (keyword.equals("LIST")) {
163 return new IMAPListResponse("LIST", data, tokenizer);
164 }
165
166 else if (keyword.equals("FLAGS")) {
167
168 return new IMAPFlagsResponse(data, tokenizer);
169 }
170
171 else if (keyword.equals("LSUB")) {
172 return new IMAPListResponse("LSUB", data, tokenizer);
173 }
174
175 else if (keyword.equals("STATUS")) {
176 return new IMAPStatusResponse(data, tokenizer);
177 }
178
179 else if (keyword.equals("SEARCH")) {
180 return new IMAPSearchResponse(data, tokenizer);
181 }
182
183 else if (keyword.equals("ACL")) {
184 return new IMAPACLResponse(data, tokenizer);
185 }
186
187 else if (keyword.equals("LISTRIGHTS")) {
188 return new IMAPListRightsResponse(data, tokenizer);
189 }
190
191 else if (keyword.equals("MYRIGHTS")) {
192 return new IMAPMyRightsResponse(data, tokenizer);
193 }
194
195 else if (keyword.equals("QUOTAROOT")) {
196 return new IMAPQuotaRootResponse(data, tokenizer);
197 }
198
199 else if (keyword.equals("QUOTA")) {
200 return new IMAPQuotaResponse(data, tokenizer);
201 }
202 else if (keyword.equals("NAMESPACE")) {
203 return new IMAPNamespaceResponse(data, tokenizer);
204 }
205 }
206
207 else if (type == Token.ATOM) {
208 String tag = token.getValue();
209 token = tokenizer.next();
210 String status = token.getValue();
211
212
213 return new IMAPTaggedResponse(tag, status, tokenizer.getRemainder(), data);
214 }
215 throw new MessagingException("Unknown server response: " + new String(data));
216 }
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232 private IMAPResponse parseUntaggedOkResponse(byte [] data, IMAPResponseTokenizer tokenizer) throws MessagingException {
233 Token token = tokenizer.peek();
234
235 if (token.getType() != '[') {
236
237
238 return new IMAPOkResponse("OK", null, tokenizer.getRemainder(), data);
239 }
240
241 tokenizer.next();
242 token = tokenizer.next();
243 String keyword = token.getValue();
244
245
246 if (keyword.equals("PERMANENTFLAGS")) {
247 return new IMAPPermanentFlagsResponse(data, tokenizer);
248 }
249
250 ArrayList arguments = new ArrayList();
251
252
253 token = tokenizer.next();
254 while (token.getType() != ']') {
255 arguments.add(token);
256 token = tokenizer.next();
257 }
258
259 return new IMAPOkResponse(keyword, arguments, tokenizer.getRemainder(), data);
260 }
261
262
263
264
265
266
267
268
269
270 public byte[] readData() throws MessagingException {
271
272 out.reset();
273
274 readBuffer();
275
276 return out.toByteArray();
277 }
278
279
280
281
282
283
284
285
286
287
288 public void readBuffer() throws MessagingException {
289 while (true) {
290 int ch = nextByte();
291
292
293 if (ch == '\r') {
294 int next = nextByte();
295 if (next == '\n') {
296
297
298 checkLiteral();
299 return;
300 }
301 }
302
303 out.write(ch);
304 }
305 }
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321 public void checkLiteral() throws MessagingException {
322 try {
323
324 int length = out.getLiteralLength();
325
326
327 if (length == -1) {
328 return;
329 }
330
331
332 out.write('\r');
333 out.write('\n');
334
335
336 if (length > 0) {
337 byte[] bytes = new byte[length];
338
339 int offset = 0;
340
341
342
343 while (length > 0) {
344 int read = -1;
345 try {
346 read = in.read(bytes, offset, length);
347 } catch (IOException e) {
348 throw new MessagingException("Unexpected read error on server connection", e);
349 }
350
351 if (read == -1) {
352 throw new MessagingException("Unexpected end of stream");
353 }
354 length -= read;
355 offset += read;
356 }
357
358
359 out.write(bytes);
360 }
361
362
363 readBuffer();
364 } catch (IOException e) {
365 e.printStackTrace();
366
367 }
368 }
369
370
371
372
373
374
375
376
377
378 protected int nextByte() throws MessagingException {
379 try {
380 int next = in.read();
381 if (next == -1) {
382 throw new MessagingException("Read error on IMAP server connection");
383 }
384 return next;
385 } catch (IOException e) {
386 throw new MessagingException("Unexpected error on server stream", e);
387 }
388 }
389
390
391 }
392