diff -r 000000000000 -r 373ffda63c9a src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/mimepull/MIMEPart.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/mimepull/MIMEPart.java Wed Apr 27 01:27:09 2016 +0800 @@ -0,0 +1,250 @@ +/* + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.xml.internal.org.jvnet.mimepull; + +import java.io.File; +import java.io.InputStream; +import java.nio.ByteBuffer; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Represents an attachment part in a MIME message. MIME message parsing is done + * lazily using a pull parser, so the part may not have all the data. {@link #read} + * and {@link #readOnce} may trigger the actual parsing the message. In fact, + * parsing of an attachment part may be triggered by calling {@link #read} methods + * on some other attachment parts. All this happens behind the scenes so the + * application developer need not worry about these details. + * + * @author Jitendra Kotamraju, Martin Grebac + */ +public class MIMEPart { + + private static final Logger LOGGER = Logger.getLogger(MIMEPart.class.getName()); + + private volatile InternetHeaders headers; + private volatile String contentId; + private String contentType; + private String contentTransferEncoding; + + volatile boolean parsed; // part is parsed or not + final MIMEMessage msg; + private final DataHead dataHead; + + MIMEPart(MIMEMessage msg) { + this.msg = msg; + this.dataHead = new DataHead(this); + } + + MIMEPart(MIMEMessage msg, String contentId) { + this(msg); + this.contentId = contentId; + } + + /** + * Can get the attachment part's content multiple times. That means + * the full content needs to be there in memory or on the file system. + * Calling this method would trigger parsing for the part's data. So + * do not call this unless it is required(otherwise, just wrap MIMEPart + * into a object that returns InputStream for e.g DataHandler) + * + * @return data for the part's content + */ + public InputStream read() { + InputStream is = null; + try { + is = MimeUtility.decode(dataHead.read(), contentTransferEncoding); + } catch (DecodingException ex) { //ignore + if (LOGGER.isLoggable(Level.WARNING)) { + LOGGER.log(Level.WARNING, null, ex); + } + } + return is; + } + + /** + * Cleans up any resources that are held by this part (for e.g. deletes + * the temp file that is used to serve this part's content). After + * calling this, one shouldn't call {@link #read()} or {@link #readOnce()} + */ + public void close() { + dataHead.close(); + } + + /** + * Can get the attachment part's content only once. The content + * will be lost after the method. Content data is not be stored + * on the file system or is not kept in the memory for the + * following case: + * - Attachement parts contents are accessed sequentially + * + * In general, take advantage of this when the data is used only + * once. + * + * @return data for the part's content + */ + public InputStream readOnce() { + InputStream is = null; + try { + is = MimeUtility.decode(dataHead.readOnce(), contentTransferEncoding); + } catch (DecodingException ex) { //ignore + if (LOGGER.isLoggable(Level.WARNING)) { + LOGGER.log(Level.WARNING, null, ex); + } + } + return is; + } + + public void moveTo(File f) { + dataHead.moveTo(f); + } + + /** + * Returns Content-ID MIME header for this attachment part + * + * @return Content-ID of the part + */ + public String getContentId() { + if (contentId == null) { + getHeaders(); + } + return contentId; + } + + /** + * Returns Content-Transfer-Encoding MIME header for this attachment part + * + * @return Content-Transfer-Encoding of the part + */ + public String getContentTransferEncoding() { + if (contentTransferEncoding == null) { + getHeaders(); + } + return contentTransferEncoding; + } + + /** + * Returns Content-Type MIME header for this attachment part + * + * @return Content-Type of the part + */ + public String getContentType() { + if (contentType == null) { + getHeaders(); + } + return contentType; + } + + private void getHeaders() { + // Trigger parsing for the part headers + while(headers == null) { + if (!msg.makeProgress()) { + if (headers == null) { + throw new IllegalStateException("Internal Error. Didn't get Headers even after complete parsing."); + } + } + } + } + + /** + * Return all the values for the specified header. + * Returns null if no headers with the + * specified name exist. + * + * @param name header name + * @return list of header values, or null if none + */ + public List getHeader(String name) { + getHeaders(); + assert headers != null; + return headers.getHeader(name); + } + + /** + * Return all the headers + * + * @return list of Header objects + */ + public List getAllHeaders() { + getHeaders(); + assert headers != null; + return headers.getAllHeaders(); + } + + /** + * Callback to set headers + * + * @param headers MIME headers for the part + */ + void setHeaders(InternetHeaders headers) { + this.headers = headers; + List ct = getHeader("Content-Type"); + this.contentType = (ct == null) ? "application/octet-stream" : ct.get(0); + List cte = getHeader("Content-Transfer-Encoding"); + this.contentTransferEncoding = (cte == null) ? "binary" : cte.get(0); + } + + /** + * Callback to notify that there is a partial content for the part + * + * @param buf content data for the part + */ + void addBody(ByteBuffer buf) { + dataHead.addBody(buf); + } + + /** + * Callback to indicate that parsing is done for this part + * (no more update events for this part) + */ + void doneParsing() { + parsed = true; + dataHead.doneParsing(); + } + + /** + * Callback to set Content-ID for this part + * @param cid Content-ID of the part + */ + void setContentId(String cid) { + this.contentId = cid; + } + + /** + * Callback to set Content-Transfer-Encoding for this part + * @param cte Content-Transfer-Encoding of the part + */ + void setContentTransferEncoding(String cte) { + this.contentTransferEncoding = cte; + } + + @Override + public String toString() { + return "Part="+contentId+":"+contentTransferEncoding; + } + +}