1
2
3
4
5
6
7
8
9
10
11
12
13 package org.abstracthorizon.mercury.maildir;
14
15 import java.util.ArrayList;
16 import java.util.Arrays;
17 import java.util.Collection;
18 import java.util.HashMap;
19 import java.util.Iterator;
20 import java.util.List;
21
22 import javax.mail.Flags;
23 import javax.mail.Folder;
24 import javax.mail.FolderNotFoundException;
25 import javax.mail.Message;
26 import javax.mail.MessagingException;
27 import javax.mail.event.ConnectionEvent;
28 import javax.mail.event.FolderEvent;
29 import javax.mail.internet.MimeMessage;
30
31 import org.abstracthorizon.mercury.maildir.util.MessageBase;
32 import org.abstracthorizon.mercury.maildir.util.MessageWrapper;
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86 public class MaildirFolder extends Folder {
87
88
89 protected MaildirStore store;
90
91
92 protected boolean opened = false;
93
94
95
96
97
98
99
100
101
102
103 protected MaildirFolderData folderData;
104
105
106
107
108
109 protected List<MessageBase> messages;
110
111
112 protected HashMap<MimeMessage, MessageWrapper> map;
113
114 protected Message[] cacheArray;
115
116
117
118
119
120
121 protected MaildirFolder(MaildirStore store, MaildirFolderData folderData) {
122 super(store);
123 this.store = store;
124 this.folderData = folderData;
125 }
126
127
128
129
130
131 public MaildirStore getMaildirStore() {
132 return store;
133 }
134
135
136
137
138
139
140 public List<MessageBase> getFolderMessages() {
141 return messages;
142 }
143
144
145
146
147
148
149 protected void setFolderMessages(List<MessageBase> messages) {
150 this.messages = messages;
151 cacheArray = null;
152 }
153
154
155
156
157
158 protected MaildirFolderData getFolderData() {
159 return folderData;
160 }
161
162
163
164
165
166 public String getName() {
167 return folderData.getName();
168 }
169
170
171
172
173
174 public String getFullName() {
175 return folderData.getFullName();
176 }
177
178
179
180
181
182
183 public Folder getParent() throws MessagingException {
184 return store.getParentFolder(folderData);
185 }
186
187
188
189
190
191
192 public boolean exists() throws MessagingException {
193 return folderData.exists();
194 }
195
196
197
198
199
200
201
202 public Folder[] list(String pattern) throws MessagingException {
203 String[] names = folderData.listNames(pattern);
204 Folder[] res = new Folder[names.length];
205
206 if (names != null) {
207 for (int i = 0; i < names.length; i++) {
208 Folder folder = store.getFolder(names[i]);
209 res[i] = folder;
210 }
211 }
212
213 return res;
214 }
215
216
217
218
219
220
221 public char getSeparator() throws MessagingException {
222 return '/';
223 }
224
225
226
227
228
229
230
231 public Folder getFolder(String name) throws MessagingException {
232 return store.getFolder(folderData.getSubFolderName(name));
233 }
234
235
236
237
238
239
240
241
242
243
244 public boolean create(int type) throws MessagingException {
245 if (isOpen()) {
246 throw new IllegalStateException("Folder is opened; "+getFullName());
247 }
248 boolean res = folderData.create(type);
249 if (res) {
250 notifyFolderListeners(FolderEvent.CREATED);
251 }
252 return res;
253 }
254
255
256
257
258
259
260
261
262
263 public boolean delete(boolean recursive) throws MessagingException {
264 if (isOpen()) {
265 throw new IllegalStateException("Folder is opened; "+getFullName());
266 }
267 boolean res = folderData.delete(recursive);
268 if (res) {
269 notifyFolderListeners(FolderEvent.DELETED);
270 }
271 return res;
272 }
273
274
275
276
277
278
279 public int getType() throws MessagingException {
280 return folderData.getType();
281 }
282
283
284
285
286
287
288
289 public boolean renameTo(Folder folder) throws MessagingException {
290 if (isOpen()) {
291 throw new IllegalStateException("Folder is opened; "+getFullName());
292 }
293
294 MaildirFolderData newFolderData = folderData.renameTo(((MaildirFolder)folder).getFolderData());
295 if (newFolderData != null) {
296 notifyFolderRenamedListeners(folder);
297 return true;
298 } else {
299 return false;
300 }
301 }
302
303
304
305
306
307
308 public void open(int mode) throws MessagingException {
309 if (!exists()) {
310 throw new FolderNotFoundException(this);
311 }
312 if (isOpen()) {
313 throw new IllegalStateException("Folder is opened; "+getFullName());
314 }
315
316 try {
317 map = new HashMap<MimeMessage, MessageWrapper>();
318 folderData.open(this);
319
320 this.mode = mode;
321 opened = true;
322 notifyConnectionListeners(ConnectionEvent.OPENED);
323 } catch (MessagingException e) {
324 throw e;
325 } catch (Exception e) {
326 throw new MessagingException("Cannot obtain messages", e);
327 }
328 }
329
330
331
332
333
334
335 public void close(boolean expunge) throws MessagingException {
336 if (!isOpen()) {
337 throw new IllegalStateException("Folder is closed; "+getFullName());
338 }
339 try {
340 if (expunge) {
341 folderData.expunge(this, false);
342 }
343 folderData.close(this);
344 } finally {
345 messages = null;
346 cacheArray = null;
347 map = null;
348 opened = false;
349 notifyConnectionListeners(ConnectionEvent.CLOSED);
350 }
351 }
352
353
354
355
356
357
358 public void appendMessages(Message[] messages) throws MessagingException {
359 if (!exists()) {
360 throw new FolderNotFoundException(this);
361 }
362 folderData.appendMessages(this, messages);
363 }
364
365
366
367
368
369
370 public Message[] expunge() throws MessagingException {
371 if (!isOpen()) {
372 throw new IllegalStateException("Folder is not opened; "+getFullName());
373 }
374 List<? extends Message> expunged = folderData.expunge(this, true);
375 Message[] res = new Message[expunged.size()];
376 return expunged.toArray(res);
377 }
378
379
380
381
382
383
384
385 protected void addMessages(List<MaildirMessage> messages, boolean notify) throws MessagingException {
386 int size = messages.size();
387 MessageBase[] wrappers = new MessageBase[size];
388 for (int i = 0; i < size; i++) {
389 MaildirMessage msg = messages.get(i);
390 wrappers[i] = addMessage(msg, i+1);
391 }
392
393 List<MessageBase> ms = Arrays.asList(wrappers);
394 if (ms.size() > 0) {
395 this.messages.addAll(ms);
396 cacheArray = null;
397
398 if (notify) {
399 Message[] msgs = new Message[ms.size()];
400 msgs = ms.toArray(msgs);
401 notifyMessageAddedListeners(msgs);
402 }
403 }
404 }
405
406
407
408
409
410
411
412
413 protected List<? extends MimeMessage> removeMessages(Collection<? extends MimeMessage> messages, boolean explicit) throws MessagingException {
414 ArrayList<MimeMessage> expunged = new ArrayList<MimeMessage>();
415
416 Iterator<? extends MimeMessage> it = messages.iterator();
417 while (it.hasNext()) {
418 MimeMessage msg = it.next();
419 MessageWrapper removed = removeMessage(msg);
420
421 if (removed != null) {
422 expunged.add(removed);
423 }
424 }
425
426 if (expunged.size() > 0) {
427 this.messages.removeAll(expunged);
428 cacheArray = null;
429 MessageBase[] msgs = new MessageBase[expunged.size()];
430 msgs = expunged.toArray(msgs);
431 int size = this.messages.size();
432 if (explicit && (size > 0)) {
433 MaildirFolderData.renumerateMessages(1, this.messages);
434 }
435 notifyMessageRemovedListeners(explicit, msgs);
436 }
437 return expunged;
438 }
439
440
441
442
443
444
445
446
447 protected MessageWrapper addMessage(MimeMessage msg, int num) throws MessagingException {
448 MessageWrapper wrapper = new MessageWrapper(this, msg, num);
449 map.put(msg, wrapper);
450 return wrapper;
451 }
452
453
454
455
456
457
458
459 protected MessageWrapper removeMessage(MimeMessage msg) throws MessagingException {
460 if (msg instanceof MessageWrapper) {
461 msg = ((MessageWrapper)msg).getMessage();
462 }
463 MessageWrapper removed = (MessageWrapper)map.get(msg);
464 if (removed != null) {
465 map.remove(msg);
466 }
467 return removed;
468 }
469
470
471
472
473
474
475
476 protected boolean hasMessage(MimeMessage msg) throws MessagingException {
477 if (msg instanceof MessageWrapper) {
478 msg = ((MessageWrapper)msg).getMessage();
479 }
480 return map.containsKey(msg);
481 }
482
483
484
485
486
487 public boolean isOpen() {
488 return opened;
489 }
490
491
492
493
494
495 public Flags getPermanentFlags() {
496 return folderData.getPermanentFlags();
497 }
498
499
500
501
502
503
504 protected void notifyMessageChangedListeners(int type, Message msg) {
505 super.notifyMessageChangedListeners(type, msg);
506 }
507
508
509
510
511
512 protected void notifyMessageAddedListeners(Message[] msgs) {
513 super.notifyMessageAddedListeners(msgs);
514 }
515
516
517
518
519
520
521 protected void notifyMessageRemovedListeners(boolean removed, Message[] msgs) {
522 super.notifyMessageRemovedListeners(removed, msgs);
523 }
524
525
526
527
528
529
530 public boolean hasNewMessages() throws MessagingException {
531 return getNewMessageCount() > 0;
532 }
533
534
535
536
537
538
539 public int getMessageCount() throws MessagingException {
540 if (!exists()) {
541 throw new FolderNotFoundException(this);
542 }
543 if (!isOpen()) {
544 return folderData.getMessageCount();
545 } else {
546 folderData.obtainMessages();
547 return messages.size();
548 }
549 }
550
551
552
553
554
555
556 public int getNewMessageCount() throws MessagingException {
557 if (!exists()) {
558 throw new FolderNotFoundException(this);
559 }
560 if (!isOpen()) {
561 return folderData.getNewMessageCount();
562 } else {
563 folderData.obtainMessages();
564 return super.getNewMessageCount();
565 }
566 }
567
568
569
570
571
572
573
574 public Message getMessage(int msgNum) throws MessagingException {
575 if (!isOpen()) {
576 throw new IllegalStateException("Folder is not opened; "+getFullName());
577 }
578 return (Message)messages.get(msgNum-1);
579 }
580
581
582
583
584
585
586 public Message[] getMessages() throws MessagingException {
587 if (!isOpen()) {
588 throw new IllegalStateException("Folder is not opened; "+getFullName());
589 }
590 if (cacheArray == null) {
591 cacheArray = new Message[messages.size()];
592 cacheArray = (Message[])messages.toArray(cacheArray);
593 }
594 return cacheArray;
595 }
596
597 }