src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/mimepull/MIMEPart.java

Thu, 31 Aug 2017 15:18:52 +0800

author
aoqi
date
Thu, 31 Aug 2017 15:18:52 +0800
changeset 637
9c07ef4934dd
parent 368
0989ad8c0860
parent 0
373ffda63c9a
permissions
-rw-r--r--

merge

     1 /*
     2  * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     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
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    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  */
    26 package com.sun.xml.internal.org.jvnet.mimepull;
    28 import java.io.File;
    29 import java.io.InputStream;
    30 import java.nio.ByteBuffer;
    31 import java.util.List;
    32 import java.util.logging.Level;
    33 import java.util.logging.Logger;
    35 /**
    36  * Represents an attachment part in a MIME message. MIME message parsing is done
    37  * lazily using a pull parser, so the part may not have all the data. {@link #read}
    38  * and {@link #readOnce} may trigger the actual parsing the message. In fact,
    39  * parsing of an attachment part may be triggered by calling {@link #read} methods
    40  * on some other attachment parts. All this happens behind the scenes so the
    41  * application developer need not worry about these details.
    42  *
    43  * @author Jitendra Kotamraju, Martin Grebac
    44  */
    45 public class MIMEPart {
    47     private static final Logger LOGGER = Logger.getLogger(MIMEPart.class.getName());
    49     private volatile InternetHeaders headers;
    50     private volatile String contentId;
    51     private String contentType;
    52     private String contentTransferEncoding;
    54     volatile boolean parsed;    // part is parsed or not
    55     final MIMEMessage msg;
    56     private final DataHead dataHead;
    58     MIMEPart(MIMEMessage msg) {
    59         this.msg = msg;
    60         this.dataHead = new DataHead(this);
    61     }
    63     MIMEPart(MIMEMessage msg, String contentId) {
    64         this(msg);
    65         this.contentId = contentId;
    66     }
    68     /**
    69      * Can get the attachment part's content multiple times. That means
    70      * the full content needs to be there in memory or on the file system.
    71      * Calling this method would trigger parsing for the part's data. So
    72      * do not call this unless it is required(otherwise, just wrap MIMEPart
    73      * into a object that returns InputStream for e.g DataHandler)
    74      *
    75      * @return data for the part's content
    76      */
    77     public InputStream read() {
    78         InputStream is = null;
    79         try {
    80             is = MimeUtility.decode(dataHead.read(), contentTransferEncoding);
    81         } catch (DecodingException ex) { //ignore
    82             if (LOGGER.isLoggable(Level.WARNING)) {
    83                 LOGGER.log(Level.WARNING, null, ex);
    84             }
    85         }
    86         return is;
    87     }
    89     /**
    90      * Cleans up any resources that are held by this part (for e.g. deletes
    91      * the temp file that is used to serve this part's content). After
    92      * calling this, one shouldn't call {@link #read()} or {@link #readOnce()}
    93      */
    94     public void close() {
    95         dataHead.close();
    96     }
    98     /**
    99      * Can get the attachment part's content only once. The content
   100      * will be lost after the method. Content data is not be stored
   101      * on the file system or is not kept in the memory for the
   102      * following case:
   103      *   - Attachement parts contents are accessed sequentially
   104      *
   105      * In general, take advantage of this when the data is used only
   106      * once.
   107      *
   108      * @return data for the part's content
   109      */
   110     public InputStream readOnce() {
   111         InputStream is = null;
   112         try {
   113             is = MimeUtility.decode(dataHead.readOnce(), contentTransferEncoding);
   114         } catch (DecodingException ex) { //ignore
   115             if (LOGGER.isLoggable(Level.WARNING)) {
   116                 LOGGER.log(Level.WARNING, null, ex);
   117             }
   118         }
   119         return is;
   120     }
   122     public void moveTo(File f) {
   123         dataHead.moveTo(f);
   124     }
   126     /**
   127      * Returns Content-ID MIME header for this attachment part
   128      *
   129      * @return Content-ID of the part
   130      */
   131     public String getContentId() {
   132         if (contentId == null) {
   133             getHeaders();
   134         }
   135         return contentId;
   136     }
   138     /**
   139      * Returns Content-Transfer-Encoding MIME header for this attachment part
   140      *
   141      * @return Content-Transfer-Encoding of the part
   142      */
   143     public String getContentTransferEncoding() {
   144         if (contentTransferEncoding == null) {
   145             getHeaders();
   146         }
   147         return contentTransferEncoding;
   148     }
   150     /**
   151      * Returns Content-Type MIME header for this attachment part
   152      *
   153      * @return Content-Type of the part
   154      */
   155     public String getContentType() {
   156         if (contentType == null) {
   157             getHeaders();
   158         }
   159         return contentType;
   160     }
   162     private void getHeaders() {
   163         // Trigger parsing for the part headers
   164         while(headers == null) {
   165             if (!msg.makeProgress()) {
   166                 if (headers == null) {
   167                     throw new IllegalStateException("Internal Error. Didn't get Headers even after complete parsing.");
   168                 }
   169             }
   170         }
   171     }
   173     /**
   174      * Return all the values for the specified header.
   175      * Returns <code>null</code> if no headers with the
   176      * specified name exist.
   177      *
   178      * @param   name header name
   179      * @return  list of header values, or null if none
   180      */
   181     public List<String> getHeader(String name) {
   182         getHeaders();
   183         assert headers != null;
   184         return headers.getHeader(name);
   185     }
   187     /**
   188      * Return all the headers
   189      *
   190      * @return list of Header objects
   191      */
   192     public List<? extends Header> getAllHeaders() {
   193         getHeaders();
   194         assert headers != null;
   195         return headers.getAllHeaders();
   196     }
   198     /**
   199      * Callback to set headers
   200      *
   201      * @param headers MIME headers for the part
   202      */
   203     void setHeaders(InternetHeaders headers) {
   204         this.headers = headers;
   205         List<String> ct = getHeader("Content-Type");
   206         this.contentType = (ct == null) ? "application/octet-stream" : ct.get(0);
   207         List<String> cte = getHeader("Content-Transfer-Encoding");
   208         this.contentTransferEncoding = (cte == null) ? "binary" : cte.get(0);
   209     }
   211     /**
   212      * Callback to notify that there is a partial content for the part
   213      *
   214      * @param buf content data for the part
   215      */
   216     void addBody(ByteBuffer buf) {
   217         dataHead.addBody(buf);
   218     }
   220     /**
   221      * Callback to indicate that parsing is done for this part
   222      * (no more update events for this part)
   223      */
   224     void doneParsing() {
   225         parsed = true;
   226         dataHead.doneParsing();
   227     }
   229     /**
   230      * Callback to set Content-ID for this part
   231      * @param cid Content-ID of the part
   232      */
   233     void setContentId(String cid) {
   234         this.contentId = cid;
   235     }
   237     /**
   238      * Callback to set Content-Transfer-Encoding for this part
   239      * @param cte Content-Transfer-Encoding of the part
   240      */
   241     void setContentTransferEncoding(String cte) {
   242         this.contentTransferEncoding = cte;
   243     }
   245     @Override
   246     public String toString() {
   247         return "Part="+contentId+":"+contentTransferEncoding;
   248     }
   250 }

mercurial