1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.apache.james.core;
23
24 import org.apache.avalon.framework.activity.Disposable;
25 import org.apache.avalon.framework.container.ContainerUtil;
26
27 import javax.activation.DataHandler;
28 import javax.mail.Address;
29 import javax.mail.Flags;
30 import javax.mail.Folder;
31 import javax.mail.Message;
32 import javax.mail.MessagingException;
33 import javax.mail.Multipart;
34 import javax.mail.Session;
35 import javax.mail.Flags.Flag;
36 import javax.mail.internet.MimeMessage;
37 import javax.mail.search.SearchTerm;
38
39 import java.io.IOException;
40 import java.io.InputStream;
41 import java.io.OutputStream;
42 import java.util.Date;
43 import java.util.Enumeration;
44
45
46
47
48
49 public class MimeMessageCopyOnWriteProxy extends MimeMessage implements
50 Disposable {
51
52
53
54
55
56
57 protected static class MessageReferenceTracker {
58
59
60
61
62 private int referenceCount = 1;
63
64
65
66
67 private MimeMessage wrapped = null;
68
69 public MessageReferenceTracker(MimeMessage ref) {
70 wrapped = ref;
71 }
72
73 protected synchronized void incrementReferenceCount() {
74
75
76
77
78
79
80
81 referenceCount++;
82 }
83
84 protected synchronized void decrementReferenceCount() {
85
86
87
88
89
90
91
92 referenceCount--;
93 if (referenceCount<=0) {
94 ContainerUtil.dispose(wrapped);
95 wrapped = null;
96 }
97 }
98
99 protected synchronized int getReferenceCount() {
100 return referenceCount;
101 }
102
103 public MimeMessage getWrapped() {
104 return wrapped;
105 }
106
107 }
108
109 protected MessageReferenceTracker refCount;
110
111
112
113
114
115
116 public MimeMessageCopyOnWriteProxy(MimeMessage original)
117 throws MessagingException {
118 this(original, false);
119 }
120
121
122
123
124
125
126 public MimeMessageCopyOnWriteProxy(MimeMessageSource original)
127 throws MessagingException {
128 this(new MimeMessageWrapper(original), true);
129 }
130
131
132
133
134
135
136
137
138 private MimeMessageCopyOnWriteProxy(MimeMessage original,
139 boolean writeable)
140 throws MessagingException {
141 super(Session.getDefaultInstance(System.getProperties(), null));
142
143 if (original instanceof MimeMessageCopyOnWriteProxy) {
144 refCount = ((MimeMessageCopyOnWriteProxy) original).refCount;
145 } else {
146 refCount = new MessageReferenceTracker(original);
147 }
148
149 if (!writeable) {
150 refCount.incrementReferenceCount();
151 }
152 }
153
154
155
156
157
158
159
160
161 protected MimeMessage getWrappedMessageForWriting() throws MessagingException {
162 synchronized (refCount) {
163 if (refCount.getReferenceCount() > 1) {
164 refCount.decrementReferenceCount();
165 refCount = new MessageReferenceTracker(new MimeMessageWrapper(refCount.getWrapped()));
166 }
167 }
168 return refCount.getWrapped();
169 }
170
171
172
173
174
175
176 public MimeMessage getWrappedMessage() {
177 return refCount.getWrapped();
178 }
179
180
181
182
183
184 public synchronized void dispose() {
185 if (refCount != null) {
186 refCount.decrementReferenceCount();
187 refCount = null;
188 }
189 }
190
191
192
193
194 public void writeTo(OutputStream os) throws IOException, MessagingException {
195 getWrappedMessage().writeTo(os);
196 }
197
198
199
200
201 public void writeTo(OutputStream os, String[] ignoreList)
202 throws IOException, MessagingException {
203 getWrappedMessage().writeTo(os, ignoreList);
204 }
205
206
207
208
209
210
211
212
213 public Address[] getFrom() throws MessagingException {
214 return getWrappedMessage().getFrom();
215 }
216
217
218
219
220 public Address[] getRecipients(Message.RecipientType type)
221 throws MessagingException {
222 return getWrappedMessage().getRecipients(type);
223 }
224
225
226
227
228 public Address[] getAllRecipients() throws MessagingException {
229 return getWrappedMessage().getAllRecipients();
230 }
231
232
233
234
235 public Address[] getReplyTo() throws MessagingException {
236 return getWrappedMessage().getReplyTo();
237 }
238
239
240
241
242 public String getSubject() throws MessagingException {
243 return getWrappedMessage().getSubject();
244 }
245
246
247
248
249 public Date getSentDate() throws MessagingException {
250 return getWrappedMessage().getSentDate();
251 }
252
253
254
255
256 public Date getReceivedDate() throws MessagingException {
257 return getWrappedMessage().getReceivedDate();
258 }
259
260
261
262
263 public int getSize() throws MessagingException {
264 return getWrappedMessage().getSize();
265 }
266
267
268
269
270 public int getLineCount() throws MessagingException {
271 return getWrappedMessage().getLineCount();
272 }
273
274
275
276
277 public String getContentType() throws MessagingException {
278 return getWrappedMessage().getContentType();
279 }
280
281
282
283
284 public boolean isMimeType(String mimeType) throws MessagingException {
285 return getWrappedMessage().isMimeType(mimeType);
286 }
287
288
289
290
291 public String getDisposition() throws MessagingException {
292 return getWrappedMessage().getDisposition();
293 }
294
295
296
297
298 public String getEncoding() throws MessagingException {
299 return getWrappedMessage().getEncoding();
300 }
301
302
303
304
305 public String getContentID() throws MessagingException {
306 return getWrappedMessage().getContentID();
307 }
308
309
310
311
312 public String getContentMD5() throws MessagingException {
313 return getWrappedMessage().getContentMD5();
314 }
315
316
317
318
319 public String getDescription() throws MessagingException {
320 return getWrappedMessage().getDescription();
321 }
322
323
324
325
326 public String[] getContentLanguage() throws MessagingException {
327 return getWrappedMessage().getContentLanguage();
328 }
329
330
331
332
333 public String getMessageID() throws MessagingException {
334 return getWrappedMessage().getMessageID();
335 }
336
337
338
339
340 public String getFileName() throws MessagingException {
341 return getWrappedMessage().getFileName();
342 }
343
344
345
346
347 public InputStream getInputStream() throws IOException, MessagingException {
348 return getWrappedMessage().getInputStream();
349 }
350
351
352
353
354 public DataHandler getDataHandler() throws MessagingException {
355 return getWrappedMessage().getDataHandler();
356 }
357
358
359
360
361 public Object getContent() throws IOException, MessagingException {
362 return getWrappedMessage().getContent();
363 }
364
365
366
367
368 public String[] getHeader(String name) throws MessagingException {
369 return getWrappedMessage().getHeader(name);
370 }
371
372
373
374
375 public String getHeader(String name, String delimiter)
376 throws MessagingException {
377 return getWrappedMessage().getHeader(name, delimiter);
378 }
379
380
381
382
383 public Enumeration getAllHeaders() throws MessagingException {
384 return getWrappedMessage().getAllHeaders();
385 }
386
387
388
389
390 public Enumeration getMatchingHeaders(String[] names)
391 throws MessagingException {
392 return getWrappedMessage().getMatchingHeaders(names);
393 }
394
395
396
397
398 public Enumeration getNonMatchingHeaders(String[] names)
399 throws MessagingException {
400 return getWrappedMessage().getNonMatchingHeaders(names);
401 }
402
403
404
405
406 public Enumeration getAllHeaderLines() throws MessagingException {
407 return getWrappedMessage().getAllHeaderLines();
408 }
409
410
411
412
413 public Enumeration getMatchingHeaderLines(String[] names)
414 throws MessagingException {
415 return getWrappedMessage().getMatchingHeaderLines(names);
416 }
417
418
419
420
421 public Enumeration getNonMatchingHeaderLines(String[] names)
422 throws MessagingException {
423 return getWrappedMessage().getNonMatchingHeaderLines(names);
424 }
425
426
427
428
429 public Flags getFlags() throws MessagingException {
430 return getWrappedMessage().getFlags();
431 }
432
433
434
435
436 public boolean isSet(Flags.Flag flag) throws MessagingException {
437 return getWrappedMessage().isSet(flag);
438 }
439
440
441
442
443 public Address getSender() throws MessagingException {
444 return getWrappedMessage().getSender();
445 }
446
447
448
449
450 public boolean match(SearchTerm arg0) throws MessagingException {
451 return getWrappedMessage().match(arg0);
452 }
453
454
455
456
457 public InputStream getRawInputStream() throws MessagingException {
458 return getWrappedMessage().getRawInputStream();
459 }
460
461
462
463
464 public Folder getFolder() {
465 return getWrappedMessage().getFolder();
466 }
467
468
469
470
471 public int getMessageNumber() {
472 return getWrappedMessage().getMessageNumber();
473 }
474
475
476
477
478 public boolean isExpunged() {
479 return getWrappedMessage().isExpunged();
480 }
481
482
483
484
485 public boolean equals(Object arg0) {
486 return getWrappedMessage().equals(arg0);
487 }
488
489
490
491
492 public int hashCode() {
493 return getWrappedMessage().hashCode();
494 }
495
496
497
498
499 public String toString() {
500 return getWrappedMessage().toString();
501 }
502
503
504
505
506
507
508
509
510 public void setFrom(Address address) throws MessagingException {
511 getWrappedMessageForWriting().setFrom(address);
512 }
513
514
515
516
517 public void setFrom() throws MessagingException {
518 getWrappedMessageForWriting().setFrom();
519 }
520
521
522
523
524 public void addFrom(Address[] addresses) throws MessagingException {
525 getWrappedMessageForWriting().addFrom(addresses);
526 }
527
528
529
530
531 public void setRecipients(Message.RecipientType type, Address[] addresses)
532 throws MessagingException {
533 getWrappedMessageForWriting().setRecipients(type, addresses);
534 }
535
536
537
538
539 public void addRecipients(Message.RecipientType type, Address[] addresses)
540 throws MessagingException {
541 getWrappedMessageForWriting().addRecipients(type, addresses);
542 }
543
544
545
546
547 public void setReplyTo(Address[] addresses) throws MessagingException {
548 getWrappedMessageForWriting().setReplyTo(addresses);
549 }
550
551
552
553
554 public void setSubject(String subject) throws MessagingException {
555 getWrappedMessageForWriting().setSubject(subject);
556 }
557
558
559
560
561 public void setSubject(String subject, String charset)
562 throws MessagingException {
563 getWrappedMessageForWriting().setSubject(subject, charset);
564 }
565
566
567
568
569 public void setSentDate(Date d) throws MessagingException {
570 getWrappedMessageForWriting().setSentDate(d);
571 }
572
573
574
575
576 public void setDisposition(String disposition) throws MessagingException {
577 getWrappedMessageForWriting().setDisposition(disposition);
578 }
579
580
581
582
583 public void setContentID(String cid) throws MessagingException {
584 getWrappedMessageForWriting().setContentID(cid);
585 }
586
587
588
589
590 public void setContentMD5(String md5) throws MessagingException {
591 getWrappedMessageForWriting().setContentMD5(md5);
592 }
593
594
595
596
597 public void setDescription(String description) throws MessagingException {
598 getWrappedMessageForWriting().setDescription(description);
599 }
600
601
602
603
604 public void setDescription(String description, String charset)
605 throws MessagingException {
606 getWrappedMessageForWriting().setDescription(description, charset);
607 }
608
609
610
611
612 public void setContentLanguage(String[] languages)
613 throws MessagingException {
614 getWrappedMessageForWriting().setContentLanguage(languages);
615 }
616
617
618
619
620 public void setFileName(String filename) throws MessagingException {
621 getWrappedMessageForWriting().setFileName(filename);
622 }
623
624
625
626
627 public void setDataHandler(DataHandler dh) throws MessagingException {
628 getWrappedMessageForWriting().setDataHandler(dh);
629 }
630
631
632
633
634 public void setContent(Object o, String type) throws MessagingException {
635 getWrappedMessageForWriting().setContent(o, type);
636 }
637
638
639
640
641 public void setText(String text) throws MessagingException {
642 getWrappedMessageForWriting().setText(text);
643 }
644
645
646
647
648 public void setText(String text, String charset) throws MessagingException {
649 getWrappedMessageForWriting().setText(text, charset);
650 }
651
652
653
654
655 public void setContent(Multipart mp) throws MessagingException {
656 getWrappedMessageForWriting().setContent(mp);
657 }
658
659
660
661
662
663 public Message reply(boolean replyToAll) throws MessagingException {
664 return getWrappedMessage().reply(replyToAll);
665 }
666
667
668
669
670 public void setHeader(String name, String value) throws MessagingException {
671 getWrappedMessageForWriting().setHeader(name, value);
672 }
673
674
675
676
677 public void addHeader(String name, String value) throws MessagingException {
678 getWrappedMessageForWriting().addHeader(name, value);
679 }
680
681
682
683
684 public void removeHeader(String name) throws MessagingException {
685 getWrappedMessageForWriting().removeHeader(name);
686 }
687
688
689
690
691 public void addHeaderLine(String line) throws MessagingException {
692 getWrappedMessageForWriting().addHeaderLine(line);
693 }
694
695
696
697
698 public void setFlags(Flags flag, boolean set) throws MessagingException {
699 getWrappedMessageForWriting().setFlags(flag, set);
700 }
701
702
703
704
705 public void saveChanges() throws MessagingException {
706 getWrappedMessageForWriting().saveChanges();
707 }
708
709
710
711
712
713
714
715
716 public void addRecipients(Message.RecipientType type, String addresses)
717 throws MessagingException {
718 getWrappedMessageForWriting().addRecipients(type, addresses);
719 }
720
721
722
723
724 public void setRecipients(Message.RecipientType type, String addresses)
725 throws MessagingException {
726 getWrappedMessageForWriting().setRecipients(type, addresses);
727 }
728
729
730
731
732 public void setSender(Address arg0) throws MessagingException {
733 getWrappedMessageForWriting().setSender(arg0);
734 }
735
736
737
738
739 public void addRecipient(RecipientType arg0, Address arg1)
740 throws MessagingException {
741 getWrappedMessageForWriting().addRecipient(arg0, arg1);
742 }
743
744
745
746
747 public void setFlag(Flag arg0, boolean arg1) throws MessagingException {
748 getWrappedMessageForWriting().setFlag(arg0, arg1);
749 }
750
751
752
753
754
755 public long getMessageSize() throws MessagingException {
756 return MimeMessageUtil.getMessageSize(getWrappedMessage());
757 }
758
759 }