1 /* |
1 /* |
2 * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. Oracle designates this |
7 * published by the Free Software Foundation. Oracle designates this |
30 |
30 |
31 |
31 |
32 package com.sun.xml.internal.messaging.saaj.packaging.mime.internet; |
32 package com.sun.xml.internal.messaging.saaj.packaging.mime.internet; |
33 |
33 |
34 |
34 |
35 import com.sun.xml.internal.messaging.saaj.packaging.mime.Header; |
|
36 import com.sun.xml.internal.messaging.saaj.packaging.mime.MessagingException; |
35 import com.sun.xml.internal.messaging.saaj.packaging.mime.MessagingException; |
37 import com.sun.xml.internal.messaging.saaj.packaging.mime.util.OutputUtil; |
36 import com.sun.xml.internal.messaging.saaj.packaging.mime.util.OutputUtil; |
38 import com.sun.xml.internal.messaging.saaj.util.ByteOutputStream; |
37 import com.sun.xml.internal.messaging.saaj.util.ByteOutputStream; |
39 import com.sun.xml.internal.messaging.saaj.util.FinalArrayList; |
38 import com.sun.xml.internal.messaging.saaj.util.FinalArrayList; |
40 |
39 |
50 import com.sun.xml.internal.org.jvnet.mimepull.MIMEPart; |
49 import com.sun.xml.internal.org.jvnet.mimepull.MIMEPart; |
51 |
50 |
52 /** |
51 /** |
53 * This class represents a MIME body part. |
52 * This class represents a MIME body part. |
54 * MimeBodyParts are contained in <code>MimeMultipart</code> |
53 * MimeBodyParts are contained in <code>MimeMultipart</code> |
55 * objects. <p> |
54 * objects. |
|
55 * <p> |
|
56 * MimeBodyPart uses the <code>InternetHeaders</code> class to parse |
|
57 * and store the headers of that body part. |
56 * |
58 * |
57 * MimeBodyPart uses the <code>InternetHeaders</code> class to parse |
59 * <hr><strong>A note on RFC 822 and MIME headers</strong> |
58 * and store the headers of that body part. <p> |
|
59 * |
|
60 * <hr><strong>A note on RFC 822 and MIME headers</strong><p> |
|
61 * |
60 * |
62 * RFC 822 header fields <strong>must</strong> contain only |
61 * RFC 822 header fields <strong>must</strong> contain only |
63 * US-ASCII characters. MIME allows non ASCII characters to be present |
62 * US-ASCII characters. MIME allows non ASCII characters to be present |
64 * in certain portions of certain headers, by encoding those characters. |
63 * in certain portions of certain headers, by encoding those characters. |
65 * RFC 2047 specifies the rules for doing this. The MimeUtility |
64 * RFC 2047 specifies the rules for doing this. The MimeUtility |
68 * <code>addHeaderLine</code> methods are responsible for enforcing |
67 * <code>addHeaderLine</code> methods are responsible for enforcing |
69 * the MIME requirements for the specified headers. In addition, these |
68 * the MIME requirements for the specified headers. In addition, these |
70 * header fields must be folded (wrapped) before being sent if they |
69 * header fields must be folded (wrapped) before being sent if they |
71 * exceed the line length limitation for the transport (1000 bytes for |
70 * exceed the line length limitation for the transport (1000 bytes for |
72 * SMTP). Received headers may have been folded. The application is |
71 * SMTP). Received headers may have been folded. The application is |
73 * responsible for folding and unfolding headers as appropriate. <p> |
72 * responsible for folding and unfolding headers as appropriate. |
74 * |
73 * |
75 * @author John Mani |
74 * @author John Mani |
76 * @author Bill Shannon |
75 * @author Bill Shannon |
77 * @see MimeUtility |
76 * @see MimeUtility |
78 */ |
77 */ |
177 * is that the MimeMultipart parser will extract each body part's bytes |
176 * is that the MimeMultipart parser will extract each body part's bytes |
178 * from a multipart stream and feed them into this constructor, without |
177 * from a multipart stream and feed them into this constructor, without |
179 * the delimiter strings. |
178 * the delimiter strings. |
180 * |
179 * |
181 * @param is the body part Input Stream |
180 * @param is the body part Input Stream |
|
181 * |
|
182 * @exception MessagingException in case of error |
182 */ |
183 */ |
183 public MimeBodyPart(InputStream is) throws MessagingException { |
184 public MimeBodyPart(InputStream is) throws MessagingException { |
184 if (!(is instanceof ByteArrayInputStream) && |
185 if (!(is instanceof ByteArrayInputStream) && |
185 !(is instanceof BufferedInputStream) && |
186 !(is instanceof BufferedInputStream) && |
186 !(is instanceof SharedInputStream)) |
187 !(is instanceof SharedInputStream)) |
214 * |
215 * |
215 * Used by providers. |
216 * Used by providers. |
216 * |
217 * |
217 * @param headers The header of this part |
218 * @param headers The header of this part |
218 * @param content bytes representing the body of this part. |
219 * @param content bytes representing the body of this part. |
|
220 * @param len content length. |
219 */ |
221 */ |
220 public MimeBodyPart(InternetHeaders headers, byte[] content, int len) { |
222 public MimeBodyPart(InternetHeaders headers, byte[] content, int len) { |
221 this.headers = headers; |
223 this.headers = headers; |
222 this.content = content; |
224 this.content = content; |
223 this.contentLength = len; |
225 this.contentLength = len; |
251 * Set the parent of this <code>MimeBodyPart</code> to be the specified |
254 * Set the parent of this <code>MimeBodyPart</code> to be the specified |
252 * <code>MimeMultipart</code>. Normally called by <code>MimeMultipart</code>'s |
255 * <code>MimeMultipart</code>. Normally called by <code>MimeMultipart</code>'s |
253 * <code>addBodyPart</code> method. <code>parent</code> may be |
256 * <code>addBodyPart</code> method. <code>parent</code> may be |
254 * <code>null</code> if the <code>MimeBodyPart</code> is being removed |
257 * <code>null</code> if the <code>MimeBodyPart</code> is being removed |
255 * from its containing <code>MimeMultipart</code>. |
258 * from its containing <code>MimeMultipart</code>. |
|
259 * @param parent parent part |
256 * @since JavaMail 1.1 |
260 * @since JavaMail 1.1 |
257 */ |
261 */ |
258 public void setParent(MimeMultipart parent) { |
262 public void setParent(MimeMultipart parent) { |
259 this.parent = parent; |
263 this.parent = parent; |
260 } |
264 } |
349 * with <strong>"text/plain; charset=foobar"</strong>. <p> |
353 * with <strong>"text/plain; charset=foobar"</strong>. <p> |
350 * |
354 * |
351 * If the <code>subType</code> of <code>mimeType</code> is the |
355 * If the <code>subType</code> of <code>mimeType</code> is the |
352 * special character '*', then the subtype is ignored during the |
356 * special character '*', then the subtype is ignored during the |
353 * comparison. |
357 * comparison. |
|
358 * |
|
359 * @param mimeType string |
|
360 * @return true if it is valid mime type |
354 */ |
361 */ |
355 public boolean isMimeType(String mimeType) { |
362 public boolean isMimeType(String mimeType) { |
356 boolean result; |
363 boolean result; |
357 // XXX - lots of room for optimization here! |
364 // XXX - lots of room for optimization here! |
358 try { |
365 try { |
373 * null is returned. <p> |
380 * null is returned. <p> |
374 * |
381 * |
375 * This implementation uses <code>getHeader(name)</code> |
382 * This implementation uses <code>getHeader(name)</code> |
376 * to obtain the requisite header field. |
383 * to obtain the requisite header field. |
377 * |
384 * |
|
385 * @return content disposition |
|
386 * @exception MessagingException in case of error |
|
387 * |
378 * @see #headers |
388 * @see #headers |
379 */ |
389 */ |
380 public String getDisposition() throws MessagingException { |
390 public String getDisposition() throws MessagingException { |
381 String s = getHeader("Content-Disposition", null); |
391 String s = getHeader("Content-Disposition", null); |
382 |
392 |
390 /** |
400 /** |
391 * Set the "Content-Disposition" header field of this body part. |
401 * Set the "Content-Disposition" header field of this body part. |
392 * If the disposition is null, any existing "Content-Disposition" |
402 * If the disposition is null, any existing "Content-Disposition" |
393 * header field is removed. |
403 * header field is removed. |
394 * |
404 * |
|
405 * @param disposition value |
|
406 * |
|
407 * @exception MessagingException in case of error |
395 * @exception IllegalStateException if this body part is |
408 * @exception IllegalStateException if this body part is |
396 * obtained from a READ_ONLY folder. |
409 * obtained from a READ_ONLY folder. |
397 */ |
410 */ |
398 public void setDisposition(String disposition) throws MessagingException { |
411 public void setDisposition(String disposition) throws MessagingException { |
399 if (disposition == null) |
412 if (disposition == null) |
421 * or its value is absent. <p> |
434 * or its value is absent. <p> |
422 * |
435 * |
423 * This implementation uses <code>getHeader(name)</code> |
436 * This implementation uses <code>getHeader(name)</code> |
424 * to obtain the requisite header field. |
437 * to obtain the requisite header field. |
425 * |
438 * |
|
439 * @return encoding |
|
440 * @exception MessagingException in case of error |
|
441 * |
426 * @see #headers |
442 * @see #headers |
427 */ |
443 */ |
428 public String getEncoding() throws MessagingException { |
444 public String getEncoding() throws MessagingException { |
429 String s = getHeader("Content-Transfer-Encoding", null); |
445 String s = getHeader("Content-Transfer-Encoding", null); |
430 |
446 |
463 * <code>null</code> if the field is unavailable or its value is |
479 * <code>null</code> if the field is unavailable or its value is |
464 * absent. <p> |
480 * absent. <p> |
465 * |
481 * |
466 * This implementation uses <code>getHeader(name)</code> |
482 * This implementation uses <code>getHeader(name)</code> |
467 * to obtain the requisite header field. |
483 * to obtain the requisite header field. |
|
484 * |
|
485 * @return conent id |
468 */ |
486 */ |
469 public String getContentID() { |
487 public String getContentID() { |
470 return getHeader("Content-ID", null); |
488 return getHeader("Content-ID", null); |
471 } |
489 } |
472 |
490 |
473 /** |
491 /** |
474 * Set the "Content-ID" header field of this body part. |
492 * Set the "Content-ID" header field of this body part. |
475 * If the <code>cid</code> parameter is null, any existing |
493 * If the <code>cid</code> parameter is null, any existing |
476 * "Content-ID" is removed. |
494 * "Content-ID" is removed. |
477 * |
495 * |
|
496 * @param cid content id |
478 * @exception IllegalStateException if this body part is |
497 * @exception IllegalStateException if this body part is |
479 * obtained from a READ_ONLY folder. |
498 * obtained from a READ_ONLY folder. |
480 * @since JavaMail 1.3 |
499 * @since JavaMail 1.3 |
481 */ |
500 */ |
482 public void setContentID(String cid) { |
501 public void setContentID(String cid) { |
491 * <code>null</code> if this field is unavailable or its value |
510 * <code>null</code> if this field is unavailable or its value |
492 * is absent. <p> |
511 * is absent. <p> |
493 * |
512 * |
494 * This implementation uses <code>getHeader(name)</code> |
513 * This implementation uses <code>getHeader(name)</code> |
495 * to obtain the requisite header field. |
514 * to obtain the requisite header field. |
|
515 * |
|
516 * @return content MD5 sum |
496 */ |
517 */ |
497 public String getContentMD5() { |
518 public String getContentMD5() { |
498 return getHeader("Content-MD5", null); |
519 return getHeader("Content-MD5", null); |
499 } |
520 } |
500 |
521 |
501 /** |
522 /** |
502 * Set the "Content-MD5" header field of this body part. |
523 * Set the "Content-MD5" header field of this body part. |
|
524 * |
|
525 * @param md5 content md5 sum |
503 * |
526 * |
504 * @exception IllegalStateException if this body part is |
527 * @exception IllegalStateException if this body part is |
505 * obtained from a READ_ONLY folder. |
528 * obtained from a READ_ONLY folder. |
506 */ |
529 */ |
507 public void setContentMD5(String md5) { |
530 public void setContentMD5(String md5) { |
514 * RFC 1766. Returns <code>null</code> if this header is not |
537 * RFC 1766. Returns <code>null</code> if this header is not |
515 * available or its value is absent. <p> |
538 * available or its value is absent. <p> |
516 * |
539 * |
517 * This implementation uses <code>getHeader(name)</code> |
540 * This implementation uses <code>getHeader(name)</code> |
518 * to obtain the requisite header field. |
541 * to obtain the requisite header field. |
|
542 * |
|
543 * @return array of language tags |
|
544 * @exception MessagingException in case of error |
519 */ |
545 */ |
520 public String[] getContentLanguage() throws MessagingException { |
546 public String[] getContentLanguage() throws MessagingException { |
521 String s = getHeader("Content-Language", null); |
547 String s = getHeader("Content-Language", null); |
522 |
548 |
523 if (s == null) |
549 if (s == null) |
661 * not available, returns the value of the "name" parameter from |
687 * not available, returns the value of the "name" parameter from |
662 * the "Content-Type" header field of this body part. |
688 * the "Content-Type" header field of this body part. |
663 * Returns <code>null</code> if both are absent. |
689 * Returns <code>null</code> if both are absent. |
664 * |
690 * |
665 * @return filename |
691 * @return filename |
|
692 * @exception MessagingException in case of error |
666 */ |
693 */ |
667 public String getFileName() throws MessagingException { |
694 public String getFileName() throws MessagingException { |
668 String filename = null; |
695 String filename = null; |
669 String s = getHeader("Content-Disposition", null); |
696 String s = getHeader("Content-Disposition", null); |
670 |
697 |
690 * Set the filename associated with this body part, if possible. <p> |
717 * Set the filename associated with this body part, if possible. <p> |
691 * |
718 * |
692 * Sets the "filename" parameter of the "Content-Disposition" |
719 * Sets the "filename" parameter of the "Content-Disposition" |
693 * header field of this body part. |
720 * header field of this body part. |
694 * |
721 * |
|
722 * @param filename filename |
|
723 * |
|
724 * @exception MessagingException in case of error |
695 * @exception IllegalStateException if this body part is |
725 * @exception IllegalStateException if this body part is |
696 * obtained from a READ_ONLY folder. |
726 * obtained from a READ_ONLY folder. |
697 */ |
727 */ |
698 public void setFileName(String filename) throws MessagingException { |
728 public void setFileName(String filename) throws MessagingException { |
699 // Set the Content-Disposition "filename" parameter |
729 // Set the Content-Disposition "filename" parameter |
767 * use this method and attempt to decode the raw data itself. <p> |
797 * use this method and attempt to decode the raw data itself. <p> |
768 * |
798 * |
769 * This implementation simply calls the <code>getContentStream</code> |
799 * This implementation simply calls the <code>getContentStream</code> |
770 * method. |
800 * method. |
771 * |
801 * |
|
802 * @return input stream |
|
803 * |
|
804 * @exception MessagingException in case of error |
|
805 * |
772 * @see #getInputStream |
806 * @see #getInputStream |
773 * @see #getContentStream |
807 * @see #getContentStream |
774 * @since JavaMail 1.2 |
808 * @since JavaMail 1.2 |
|
809 * |
775 */ |
810 */ |
776 public InputStream getRawInputStream() throws MessagingException { |
811 public InputStream getRawInputStream() throws MessagingException { |
777 return getContentStream(); |
812 return getContentStream(); |
778 } |
813 } |
779 |
814 |
780 /** |
815 /** |
781 * Return a DataHandler for this body part's content. <p> |
816 * Return a DataHandler for this body part's content. <p> |
782 * |
817 * |
783 * The implementation provided here works just like the |
818 * The implementation provided here works just like the |
784 * the implementation in MimeMessage. |
819 * the implementation in MimeMessage. |
|
820 * |
|
821 * @return data handler |
785 */ |
822 */ |
786 public DataHandler getDataHandler() { |
823 public DataHandler getDataHandler() { |
787 if (mimePart != null) { |
824 if (mimePart != null) { |
788 //return an inputstream |
825 //return an inputstream |
789 return new DataHandler(new DataSource() { |
826 return new DataHandler(new DataSource() { |
790 |
827 |
|
828 @Override |
791 public InputStream getInputStream() throws IOException { |
829 public InputStream getInputStream() throws IOException { |
792 return mimePart.read(); |
830 return mimePart.read(); |
793 } |
831 } |
794 |
832 |
|
833 @Override |
795 public OutputStream getOutputStream() throws IOException { |
834 public OutputStream getOutputStream() throws IOException { |
796 throw new UnsupportedOperationException("getOutputStream cannot be supported : You have enabled LazyAttachments Option"); |
835 throw new UnsupportedOperationException("getOutputStream cannot be supported : You have enabled LazyAttachments Option"); |
797 } |
836 } |
798 |
837 |
|
838 @Override |
799 public String getContentType() { |
839 public String getContentType() { |
800 return mimePart.getContentType(); |
840 return mimePart.getContentType(); |
801 } |
841 } |
802 |
842 |
|
843 @Override |
803 public String getName() { |
844 public String getName() { |
804 return "MIMEPart Wrapped DataSource"; |
845 return "MIMEPart Wrapped DataSource"; |
805 } |
846 } |
806 }); |
847 }); |
807 } |
848 } |
888 * to scan all the characters to determine what charset to |
929 * to scan all the characters to determine what charset to |
889 * use. <p> |
930 * use. <p> |
890 * If the charset is already known, use the |
931 * If the charset is already known, use the |
891 * setText() version that takes the charset parameter. |
932 * setText() version that takes the charset parameter. |
892 * |
933 * |
|
934 * @param text string |
|
935 * |
893 * @see #setText(String text, String charset) |
936 * @see #setText(String text, String charset) |
894 */ |
937 */ |
895 public void setText(String text) { |
938 public void setText(String text) { |
896 setText(text, null); |
939 setText(text, null); |
897 } |
940 } |
900 * Convenience method that sets the given String as this part's |
943 * Convenience method that sets the given String as this part's |
901 * content, with a MIME type of "text/plain" and the specified |
944 * content, with a MIME type of "text/plain" and the specified |
902 * charset. The given Unicode string will be charset-encoded |
945 * charset. The given Unicode string will be charset-encoded |
903 * using the specified charset. The charset is also used to set |
946 * using the specified charset. The charset is also used to set |
904 * the "charset" parameter. |
947 * the "charset" parameter. |
|
948 * |
|
949 * @param text string |
|
950 * @param charset character set |
905 */ |
951 */ |
906 public void setText(String text, String charset) { |
952 public void setText(String text, String charset) { |
907 if (charset == null) { |
953 if (charset == null) { |
908 if (MimeUtility.checkAscii(text) != MimeUtility.ALL_ASCII) |
954 if (MimeUtility.checkAscii(text) != MimeUtility.ALL_ASCII) |
909 charset = MimeUtility.getDefaultMIMECharset(); |
955 charset = MimeUtility.getDefaultMIMECharset(); |
930 } |
976 } |
931 |
977 |
932 /** |
978 /** |
933 * Output the body part as an RFC 822 format stream. |
979 * Output the body part as an RFC 822 format stream. |
934 * |
980 * |
935 * @exception MessagingException |
981 * @param os output stream |
|
982 * |
|
983 * @exception MessagingException in case of error |
936 * @exception IOException if an error occurs writing to the |
984 * @exception IOException if an error occurs writing to the |
937 * stream or if an error is generated |
985 * stream or if an error is generated |
938 * by the javax.activation layer. |
986 * by the javax.activation layer. |
939 * @see DataHandler#writeTo |
987 * @see DataHandler#writeTo |
940 */ |
988 */ |
1031 headers.addHeader(name, value); |
1079 headers.addHeader(name, value); |
1032 } |
1080 } |
1033 |
1081 |
1034 /** |
1082 /** |
1035 * Remove all headers with this name. |
1083 * Remove all headers with this name. |
|
1084 * |
|
1085 * @param name header name |
1036 */ |
1086 */ |
1037 public void removeHeader(String name) { |
1087 public void removeHeader(String name) { |
1038 headers.removeHeader(name); |
1088 headers.removeHeader(name); |
1039 } |
1089 } |
1040 |
1090 |
1041 /** |
1091 /** |
1042 * Return all the headers from this Message as an Enumeration of |
1092 * Return all the headers from this Message as an Enumeration of |
1043 * Header objects. |
1093 * Header objects. |
1044 */ |
1094 * |
1045 public List<? extends Header> getAllHeaders() { |
1095 * @return all headers |
|
1096 */ |
|
1097 public FinalArrayList<hdr> getAllHeaders() { |
1046 return headers.getAllHeaders(); |
1098 return headers.getAllHeaders(); |
1047 } |
1099 } |
1048 |
1100 |
1049 |
1101 |
1050 /** |
1102 /** |
1051 * Add a header line to this body part |
1103 * Add a header line to this body part |
|
1104 * |
|
1105 * @param line header line to add |
1052 */ |
1106 */ |
1053 public void addHeaderLine(String line) { |
1107 public void addHeaderLine(String line) { |
1054 headers.addHeaderLine(line); |
1108 headers.addHeaderLine(line); |
1055 } |
1109 } |
1056 |
1110 |
1073 * need to resync our headers. |
1127 * need to resync our headers. |
1074 * |
1128 * |
1075 * <br> |
1129 * <br> |
1076 * In both cases this method is typically called by the |
1130 * In both cases this method is typically called by the |
1077 * <code>Message.saveChanges</code> method. |
1131 * <code>Message.saveChanges</code> method. |
|
1132 * |
|
1133 * @exception MessagingException in case of error. |
1078 */ |
1134 */ |
1079 protected void updateHeaders() throws MessagingException { |
1135 protected void updateHeaders() throws MessagingException { |
1080 DataHandler dh = getDataHandler(); |
1136 DataHandler dh = getDataHandler(); |
1081 /* |
1137 /* |
1082 * Code flow indicates null is never returned from |
1138 * Code flow indicates null is never returned from |