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

changeset 0
373ffda63c9a
child 637
9c07ef4934dd
equal deleted inserted replaced
-1:000000000000 0:373ffda63c9a
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 */
25
26 package com.sun.xml.internal.org.jvnet.mimepull;
27
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;
34
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 {
46
47 private static final Logger LOGGER = Logger.getLogger(MIMEPart.class.getName());
48
49 private volatile InternetHeaders headers;
50 private volatile String contentId;
51 private String contentType;
52 private String contentTransferEncoding;
53
54 volatile boolean parsed; // part is parsed or not
55 final MIMEMessage msg;
56 private final DataHead dataHead;
57
58 MIMEPart(MIMEMessage msg) {
59 this.msg = msg;
60 this.dataHead = new DataHead(this);
61 }
62
63 MIMEPart(MIMEMessage msg, String contentId) {
64 this(msg);
65 this.contentId = contentId;
66 }
67
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 }
88
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 }
97
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 }
121
122 public void moveTo(File f) {
123 dataHead.moveTo(f);
124 }
125
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 }
137
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 }
149
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 }
161
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 }
172
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 }
186
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 }
197
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 }
210
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 }
219
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 }
228
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 }
236
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 }
244
245 @Override
246 public String toString() {
247 return "Part="+contentId+":"+contentTransferEncoding;
248 }
249
250 }

mercurial