< prev index next >

jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/packaging/mime/internet/MimeMultipart.java

Print this page




  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 /*
  27  * @(#)MimeMultipart.java     1.31 03/01/29
  28  */
  29 
  30 
  31 
  32 package com.sun.xml.internal.messaging.saaj.packaging.mime.internet;
  33 
  34 import java.io.*;
  35 
  36 import javax.activation.DataSource;
  37 
  38 import com.sun.xml.internal.messaging.saaj.packaging.mime.*;
  39 import com.sun.xml.internal.messaging.saaj.packaging.mime.util.*;
  40 import com.sun.xml.internal.messaging.saaj.util.FinalArrayList;
  41 import com.sun.xml.internal.messaging.saaj.util.ByteOutputStream;

  42 import com.sun.xml.internal.messaging.saaj.util.SAAJUtil;
  43 







  44 /**
  45  * The MimeMultipart class is an implementation
  46  * that uses MIME conventions for the multipart data. <p>
  47  *
  48  * A MimeMultipart is obtained from a MimeBodyPart whose primary type
  49  * is "multipart" (by invoking the part's <code>getContent()</code> method)
  50  * or it can be created by a client as part of creating a new MimeMessage. <p>
  51  *
  52  * The default multipart subtype is "mixed".  The other multipart
  53  * subtypes, such as "alternative", "related", and so on, can be
  54  * implemented as subclasses of MimeMultipart with additional methods
  55  * to implement the additional semantics of that type of multipart
  56  * content. The intent is that service providers, mail JavaBean writers
  57  * and mail clients will write many such subclasses and their Command
  58  * Beans, and will install them into the JavaBeans Activation
  59  * Framework, so that any JavaMail implementation and its clients can
  60  * transparently find and use these classes. Thus, a MIME multipart
  61  * handler is treated just like any other type handler, thereby
  62  * decoupling the process of providing multipart handlers from the
  63  * JavaMail API. Lacking these additional MimeMultipart subclasses,


 309      */
 310     protected  void parse() throws MessagingException {
 311         if (parsed)
 312             return;
 313 
 314         InputStream in;
 315         SharedInputStream sin = null;
 316         long start = 0, end = 0;
 317         boolean foundClosingBoundary = false;
 318 
 319         try {
 320             in = ds.getInputStream();
 321             if (!(in instanceof ByteArrayInputStream) &&
 322                 !(in instanceof BufferedInputStream) &&
 323                 !(in instanceof SharedInputStream))
 324                 in = new BufferedInputStream(in);
 325         } catch (Exception ex) {
 326             throw new MessagingException("No inputstream from datasource");
 327         }
 328         if (in instanceof SharedInputStream)
 329             sin = (SharedInputStream)in;
 330 
 331         String boundary = "--" + contentType.getParameter("boundary");
 332         byte[] bndbytes = ASCIIUtility.getBytes(boundary);
 333         int bl = bndbytes.length;
 334 
 335         ByteOutputStream buf = null;
 336         try {
 337             // Skip the preamble
 338             LineInputStream lin = new LineInputStream(in);
 339             String line;
 340             while ((line = lin.readLine()) != null) {
 341                 /*
 342                  * Strip trailing whitespace.  Can't use trim method
 343                  * because it's too aggressive.  Some bogus MIME
 344                  * messages will include control characters in the
 345                  * boundary string.
 346                  */
 347                 int i;
 348                 for (i = line.length() - 1; i >= 0; i--) {
 349                     char c = line.charAt(i);


 380                 } else {
 381                     // collect the headers for this body part
 382                     headers = createInternetHeaders(in);
 383                 }
 384 
 385                 if (!in.markSupported())
 386                     throw new MessagingException("Stream doesn't support mark");
 387 
 388                 buf = null;
 389                 // if we don't have a shared input stream, we copy the data
 390                 if (sin == null)
 391                     buf = new ByteOutputStream();
 392                 int b;
 393                 boolean bol = true;    // beginning of line flag
 394                 // the two possible end of line characters
 395                 int eol1 = -1, eol2 = -1;
 396 
 397                 /*
 398                  * Read and save the content bytes in buf.
 399                  */
 400                 for (;;) {
 401                     if (bol) {
 402                         /*
 403                          * At the beginning of a line, check whether the
 404                          * next line is a boundary.
 405                          */
 406                         int i;
 407                         in.mark(bl + 4 + 1000); // bnd + "--\r\n" + lots of LWSP
 408                         // read bytes, matching against the boundary
 409                         for (i = 0; i < bl; i++)
 410                             if (in.read() != bndbytes[i])
 411                                 break;
 412                         if (i == bl) {
 413                             // matched the boundary, check for last boundary
 414                             int b2 = in.read();
 415                             if (b2 == '-') {
 416                                 if (in.read() == '-') {
 417                                     done = true;
 418                                     foundClosingBoundary = true;
 419                                     break;      // ignore trailing text
 420                                 }


 474                     }
 475                 }
 476 
 477                 /*
 478                  * Create a MimeBody element to represent this body part.
 479                  */
 480                 MimeBodyPart part;
 481                 if (sin != null)
 482                     part = createMimeBodyPart(sin.newStream(start, end));
 483                 else
 484                     part = createMimeBodyPart(headers, buf.getBytes(), buf.getCount());
 485                 addBodyPart(part);
 486             }
 487         } catch (IOException ioex) {
 488             throw new MessagingException("IO Error", ioex);
 489         } finally {
 490             if (buf != null)
 491                 buf.close();
 492         }
 493 
 494         if (!ignoreMissingEndBoundary && !foundClosingBoundary && sin== null) {
 495             throw new MessagingException("Missing End Boundary for Mime Package : EOF while skipping headers");
 496         }
 497         parsed = true;
 498     }
 499 
 500     /**
 501      * Create and return an InternetHeaders object that loads the
 502      * headers from the given InputStream.  Subclasses can override
 503      * this method to return a subclass of InternetHeaders, if
 504      * necessary.  This implementation simply constructs and returns
 505      * an InternetHeaders object.
 506      *
 507      * @param   is      the InputStream to read the headers from.
 508      * @return headers.
 509      * @exception       MessagingException in case of error.
 510      * @since           JavaMail 1.2
 511      */
 512     protected InternetHeaders createInternetHeaders(InputStream is)
 513                                 throws MessagingException {
 514         return new InternetHeaders(is);




  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 /*
  27  * @(#)MimeMultipart.java     1.31 03/01/29
  28  */
  29 
  30 
  31 
  32 package com.sun.xml.internal.messaging.saaj.packaging.mime.internet;
  33 
  34 import com.sun.xml.internal.messaging.saaj.packaging.mime.MessagingException;
  35 import com.sun.xml.internal.messaging.saaj.packaging.mime.MultipartDataSource;
  36 import com.sun.xml.internal.messaging.saaj.packaging.mime.util.ASCIIUtility;
  37 import com.sun.xml.internal.messaging.saaj.packaging.mime.util.LineInputStream;
  38 import com.sun.xml.internal.messaging.saaj.packaging.mime.util.OutputUtil;


  39 import com.sun.xml.internal.messaging.saaj.util.ByteOutputStream;
  40 import com.sun.xml.internal.messaging.saaj.util.FinalArrayList;
  41 import com.sun.xml.internal.messaging.saaj.util.SAAJUtil;
  42 
  43 import javax.activation.DataSource;
  44 import java.io.BufferedInputStream;
  45 import java.io.ByteArrayInputStream;
  46 import java.io.IOException;
  47 import java.io.InputStream;
  48 import java.io.OutputStream;
  49 
  50 /**
  51  * The MimeMultipart class is an implementation
  52  * that uses MIME conventions for the multipart data. <p>
  53  *
  54  * A MimeMultipart is obtained from a MimeBodyPart whose primary type
  55  * is "multipart" (by invoking the part's <code>getContent()</code> method)
  56  * or it can be created by a client as part of creating a new MimeMessage. <p>
  57  *
  58  * The default multipart subtype is "mixed".  The other multipart
  59  * subtypes, such as "alternative", "related", and so on, can be
  60  * implemented as subclasses of MimeMultipart with additional methods
  61  * to implement the additional semantics of that type of multipart
  62  * content. The intent is that service providers, mail JavaBean writers
  63  * and mail clients will write many such subclasses and their Command
  64  * Beans, and will install them into the JavaBeans Activation
  65  * Framework, so that any JavaMail implementation and its clients can
  66  * transparently find and use these classes. Thus, a MIME multipart
  67  * handler is treated just like any other type handler, thereby
  68  * decoupling the process of providing multipart handlers from the
  69  * JavaMail API. Lacking these additional MimeMultipart subclasses,


 315      */
 316     protected  void parse() throws MessagingException {
 317         if (parsed)
 318             return;
 319 
 320         InputStream in;
 321         SharedInputStream sin = null;
 322         long start = 0, end = 0;
 323         boolean foundClosingBoundary = false;
 324 
 325         try {
 326             in = ds.getInputStream();
 327             if (!(in instanceof ByteArrayInputStream) &&
 328                     !(in instanceof BufferedInputStream) &&
 329                     !(in instanceof SharedInputStream))
 330                 in = new BufferedInputStream(in);
 331         } catch (Exception ex) {
 332             throw new MessagingException("No inputstream from datasource");
 333         }
 334         if (in instanceof SharedInputStream)
 335             sin = (SharedInputStream) in;
 336 
 337         String boundary = "--" + contentType.getParameter("boundary");
 338         byte[] bndbytes = ASCIIUtility.getBytes(boundary);
 339         int bl = bndbytes.length;
 340 
 341         ByteOutputStream buf = null;
 342         try {
 343             // Skip the preamble
 344             LineInputStream lin = new LineInputStream(in);
 345             String line;
 346             while ((line = lin.readLine()) != null) {
 347         /*
 348          * Strip trailing whitespace.  Can't use trim method
 349          * because it's too aggressive.  Some bogus MIME
 350          * messages will include control characters in the
 351          * boundary string.
 352          */
 353                 int i;
 354                 for (i = line.length() - 1; i >= 0; i--) {
 355                     char c = line.charAt(i);


 386                 } else {
 387                     // collect the headers for this body part
 388                     headers = createInternetHeaders(in);
 389                 }
 390 
 391                 if (!in.markSupported())
 392                     throw new MessagingException("Stream doesn't support mark");
 393 
 394                 buf = null;
 395                 // if we don't have a shared input stream, we copy the data
 396                 if (sin == null)
 397                     buf = new ByteOutputStream();
 398                 int b;
 399                 boolean bol = true;    // beginning of line flag
 400                 // the two possible end of line characters
 401                 int eol1 = -1, eol2 = -1;
 402 
 403                 /*
 404                  * Read and save the content bytes in buf.
 405                  */
 406                 for (; ; ) {
 407                     if (bol) {
 408                         /*
 409                          * At the beginning of a line, check whether the
 410                          * next line is a boundary.
 411                          */
 412                         int i;
 413                         in.mark(bl + 4 + 1000); // bnd + "--\r\n" + lots of LWSP
 414                         // read bytes, matching against the boundary
 415                         for (i = 0; i < bl; i++)
 416                             if (in.read() != bndbytes[i])
 417                                 break;
 418                         if (i == bl) {
 419                             // matched the boundary, check for last boundary
 420                             int b2 = in.read();
 421                             if (b2 == '-') {
 422                                 if (in.read() == '-') {
 423                                     done = true;
 424                                     foundClosingBoundary = true;
 425                                     break;    // ignore trailing text
 426                                 }


 480                     }
 481                 }
 482 
 483                 /*
 484                  * Create a MimeBody element to represent this body part.
 485                  */
 486                 MimeBodyPart part;
 487                 if (sin != null)
 488                     part = createMimeBodyPart(sin.newStream(start, end));
 489                 else
 490                     part = createMimeBodyPart(headers, buf.getBytes(), buf.getCount());
 491                 addBodyPart(part);
 492             }
 493         } catch (IOException ioex) {
 494             throw new MessagingException("IO Error", ioex);
 495         } finally {
 496             if (buf != null)
 497                 buf.close();
 498         }
 499 
 500         if (!ignoreMissingEndBoundary && !foundClosingBoundary && sin == null) {
 501             throw new MessagingException("Missing End Boundary for Mime Package : EOF while skipping headers");
 502         }
 503         parsed = true;
 504     }
 505 
 506     /**
 507      * Create and return an InternetHeaders object that loads the
 508      * headers from the given InputStream.  Subclasses can override
 509      * this method to return a subclass of InternetHeaders, if
 510      * necessary.  This implementation simply constructs and returns
 511      * an InternetHeaders object.
 512      *
 513      * @param   is      the InputStream to read the headers from.
 514      * @return headers.
 515      * @exception       MessagingException in case of error.
 516      * @since           JavaMail 1.2
 517      */
 518     protected InternetHeaders createInternetHeaders(InputStream is)
 519                 throws MessagingException {
 520         return new InternetHeaders(is);


< prev index next >