jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/packaging/mime/internet/MimeBodyPart.java
changeset 43852 93a527059d8a
parent 36263 d5333008e409
equal deleted inserted replaced
43752:3c68ef249093 43852:93a527059d8a
     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;
   240         }
   242         }
   241     }
   243     }
   242     /**
   244     /**
   243      * Return the containing <code>MimeMultipart</code> object,
   245      * Return the containing <code>MimeMultipart</code> object,
   244      * or <code>null</code> if not known.
   246      * or <code>null</code> if not known.
       
   247      * @return parent part.
   245      */
   248      */
   246     public MimeMultipart getParent() {
   249     public MimeMultipart getParent() {
   247         return parent;
   250         return parent;
   248     }
   251     }
   249 
   252 
   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