1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.geronimo.javamail.store.pop3;
21
22 import java.util.List;
23
24 import javax.mail.FetchProfile;
25 import javax.mail.Flags;
26 import javax.mail.Folder;
27 import javax.mail.FolderClosedException;
28 import javax.mail.Message;
29 import javax.mail.MessagingException;
30 import javax.mail.MethodNotSupportedException;
31 import javax.mail.Session;
32 import javax.mail.Store;
33 import javax.mail.URLName;
34 import javax.mail.event.ConnectionEvent;
35
36 import org.apache.geronimo.javamail.store.pop3.connection.POP3Connection;
37 import org.apache.geronimo.javamail.store.pop3.connection.POP3StatusResponse;
38
39
40
41
42
43
44
45
46
47
48
49
50 public class POP3Folder extends Folder {
51
52 protected boolean isFolderOpen = false;
53
54 protected int mode;
55
56 protected int msgCount;
57
58 private POP3Message[] messageCache;
59
60
61
62 protected String fullName;
63
64 protected boolean exists = false;
65
66 protected int folderType;
67
68
69
70
71
72
73
74
75
76
77
78 public POP3Folder(POP3Store store, String name) {
79 super(store);
80 this.fullName = name;
81
82 if (name.equalsIgnoreCase("INPUT")) {
83 exists = true;
84 }
85
86 folderType = Folder.HOLDS_MESSAGES;
87 }
88
89
90
91
92
93
94
95
96 public String getName() {
97
98 return fullName;
99 }
100
101
102
103
104
105
106
107 public String getFullName() {
108 return fullName;
109 }
110
111
112
113
114
115
116
117 public Folder getParent() throws MessagingException {
118
119
120 return store.getDefaultFolder();
121 }
122
123
124
125
126
127
128
129
130
131 public boolean exists() throws MessagingException {
132
133 return exists;
134 }
135
136 public Folder[] list(String pattern) throws MessagingException {
137 throw new MethodNotSupportedException("Only INBOX is supported in POP3, no sub folders");
138 }
139
140
141
142
143 public char getSeparator() throws MessagingException {
144 return '\0';
145 }
146
147
148
149
150
151
152
153
154 public int getType() throws MessagingException {
155 return folderType;
156 }
157
158
159
160
161
162
163
164
165
166
167 public boolean create(int type) throws MessagingException {
168 return false;
169 }
170
171
172
173
174
175
176
177 public boolean hasNewMessages() throws MessagingException {
178 return false;
179 }
180
181 public Folder getFolder(String name) throws MessagingException {
182 throw new MethodNotSupportedException("Only INBOX is supported in POP3, no sub folders");
183 }
184
185 public boolean delete(boolean recurse) throws MessagingException {
186 throw new MethodNotSupportedException("Only INBOX is supported in POP3 and INBOX cannot be deleted");
187 }
188
189 public boolean renameTo(Folder f) throws MessagingException {
190 throw new MethodNotSupportedException("Only INBOX is supported in POP3 and INBOX cannot be renamed");
191 }
192
193
194
195
196 public void open(int mode) throws MessagingException {
197
198 checkClosed();
199
200
201 POP3Connection connection = getConnection();
202
203 try {
204 POP3StatusResponse res = connection.retrieveMailboxStatus();
205 this.mode = mode;
206 this.isFolderOpen = true;
207 this.msgCount = res.getNumMessages();
208
209
210
211
212
213
214 messageCache = new POP3Message[msgCount];
215 } catch (Exception e) {
216 throw new MessagingException("Unable to execute STAT command", e);
217 }
218 finally {
219
220 releaseConnection(connection);
221 }
222
223 notifyConnectionListeners(ConnectionEvent.OPENED);
224 }
225
226
227
228
229
230
231
232
233 public void close(boolean expunge) throws MessagingException {
234
235 checkOpen();
236
237
238 POP3Connection connection = getConnection();
239 try {
240
241
242
243 connection.reset();
244
245 expungeDeletedMessages(connection);
246 } finally {
247
248 releaseConnection(connection);
249
250
251 cleanupFolder(false);
252 }
253 }
254
255
256
257
258
259
260
261 protected void expungeDeletedMessages(POP3Connection connection) throws MessagingException {
262 if (mode == READ_WRITE) {
263 for (int i = 0; i < messageCache.length; i++) {
264 POP3Message msg = messageCache[i];
265 if (msg != null) {
266
267
268
269 if (msg.isSet(Flags.Flag.DELETED)) {
270 try {
271 connection.deleteMessage(i + 1);
272 } catch (MessagingException e) {
273 throw new MessagingException("Exception deleting message number " + (i + 1), e);
274 }
275 }
276 }
277 }
278 }
279 }
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295 protected void cleanupFolder(boolean disconnected) throws MessagingException {
296 messageCache = null;
297 isFolderOpen = false;
298 notifyConnectionListeners(ConnectionEvent.CLOSED);
299 }
300
301
302
303
304
305
306
307
308
309
310 synchronized POP3Connection getMessageConnection() throws MessagingException {
311
312
313 return getConnection();
314 }
315
316
317
318
319
320
321
322
323
324 void releaseMessageConnection(POP3Connection connection) throws MessagingException {
325
326 releaseConnection(connection);
327 }
328
329 public boolean isOpen() {
330
331 if (!isFolderOpen) {
332 return false;
333 }
334
335 try {
336
337
338 if (!((POP3Store)store).isConnected()) {
339 close(false);
340 }
341 } catch (MessagingException e) {
342 }
343 return isFolderOpen;
344 }
345
346 public Flags getPermanentFlags() {
347
348
349
350
351
352
353
354 return new Flags();
355 }
356
357
358
359
360
361
362
363 public int getMessageCount() throws MessagingException {
364
365 return msgCount;
366 }
367
368
369
370
371
372
373
374 public Message getMessage(int msgNum) throws MessagingException {
375
376 checkOpen();
377 if (msgNum < 1 || msgNum > getMessageCount()) {
378 throw new MessagingException("Invalid Message number");
379 }
380
381 Message msg = messageCache[msgNum - 1];
382 if (msg == null) {
383 msg = new POP3Message(this, msgNum);
384 messageCache[msgNum - 1] = (POP3Message)msg;
385 }
386
387 return msg;
388 }
389
390 public void appendMessages(Message[] msgs) throws MessagingException {
391 throw new MethodNotSupportedException("Message appending is not supported in POP3");
392
393 }
394
395 public Message[] expunge() throws MessagingException {
396 throw new MethodNotSupportedException("Expunge is not supported in POP3");
397 }
398
399 public int getMode() throws IllegalStateException {
400
401 checkOpen();
402 return mode;
403 }
404
405
406
407
408
409
410
411
412 public synchronized void fetch(Message[] msgs, FetchProfile fp) throws MessagingException {
413
414 checkOpen();
415 for (int i = 0; i < msgs.length; i++) {
416 Message msg = msgs[i];
417
418 if (fp.contains(FetchProfile.Item.ENVELOPE)) {
419
420
421 msg.getHeader("Subject");
422 msg.getSize();
423 }
424 if (fp.contains(FetchProfile.Item.CONTENT_INFO)) {
425
426
427 ((POP3Message)msg).loadContent();
428 msg.getSize();
429 }
430
431 if (fp.contains(FetchProfile.Item.FLAGS)) {
432 msg.getFlags();
433 }
434
435 if (fp.getHeaderNames().length > 0) {
436
437 msg.getHeader("Subject");
438 }
439 }
440 }
441
442
443
444
445
446
447
448
449
450 public synchronized String getUID(Message msg) throws MessagingException {
451 checkOpen();
452
453 return ((POP3Message)msg).getUID();
454 }
455
456
457
458
459
460
461
462
463 private void checkOpen() throws IllegalStateException {
464 if (!isFolderOpen) {
465 throw new IllegalStateException("Folder is not Open");
466 }
467 }
468
469
470 private void checkClosed() throws IllegalStateException {
471 if (isFolderOpen) {
472 throw new IllegalStateException("Folder is Open");
473 }
474 }
475
476
477
478
479
480
481
482
483
484
485
486 public void notifyMessageChangedListeners(int type, Message m) {
487 super.notifyMessageChangedListeners(type, m);
488 }
489
490
491
492
493
494
495
496
497
498 protected synchronized POP3Connection getConnection() throws MessagingException {
499
500 return ((POP3Store)store).getFolderConnection(this);
501 }
502
503
504
505
506
507
508
509
510
511 protected void releaseConnection(POP3Connection connection) throws MessagingException {
512
513 ((POP3Store)store).releaseFolderConnection(this, connection);
514 }
515 }