1 /*
2 * $Id: AttachmentPart.java,v 1.11 2005/08/17 08:13:01 vj135062 Exp $
3 * $Revision: 1.11 $
4 * $Date: 2005/08/17 08:13:01 $
5 */
6
7 /*
8 * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
9 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
10 *
11 * This code is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License version 2 only, as
13 * published by the Free Software Foundation. Sun designates this
14 * particular file as subject to the "Classpath" exception as provided
15 * by Sun in the LICENSE file that accompanied this code.
16 *
17 * This code is distributed in the hope that it will be useful, but WITHOUT
18 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 * version 2 for more details (a copy is included in the LICENSE file that
21 * accompanied this code).
22 *
23 * You should have received a copy of the GNU General Public License version
24 * 2 along with this work; if not, write to the Free Software Foundation,
25 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
26 *
27 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
28 * CA 95054 USA or visit www.sun.com if you need additional information or
29 * have any questions.
30 */
31 package javax.xml.soap;
32
33 import java.io.InputStream;
34 import java.io.Reader;
35 import java.util.Iterator;
36
37 import javax.activation.DataHandler;
38
39 /**
40 * A single attachment to a <code>SOAPMessage</code> object. A <code>SOAPMessage</code>
41 * object may contain zero, one, or many <code>AttachmentPart</code> objects.
42 * Each <code>AttachmentPart</code> object consists of two parts,
43 * application-specific content and associated MIME headers. The
44 * MIME headers consists of name/value pairs that can be used to
45 * identify and describe the content.
46 * <p>
47 * An <code>AttachmentPart</code> object must conform to certain standards.
48 * <OL>
49 * <LI>It must conform to <a href="http://www.ietf.org/rfc/rfc2045.txt">
50 * MIME [RFC2045] standards</a>
51 * <LI>It MUST contain content
52 * <LI>The header portion MUST include the following header:
53 * <UL>
54 * <LI><code>Content-Type</code><br>
55 * This header identifies the type of data in the content of an
56 * <code>AttachmentPart</code> object and MUST conform to [RFC2045].
57 * The following is an example of a Content-Type header:
58 * <PRE>
59 * Content-Type: application/xml
60 * </PRE>
61 * The following line of code, in which <code>ap</code> is an
62 * <code>AttachmentPart</code> object, sets the header shown in
63 * the previous example.
64 * <PRE>
65 * ap.setMimeHeader("Content-Type", "application/xml");
66 * </PRE>
67 * <p>
68 * </UL>
69 * </OL>
70 * <p>
71 * There are no restrictions on the content portion of an <code>
72 * AttachmentPart</code> object. The content may be anything from a
73 * simple plain text object to a complex XML document or image file.
74 *
75 * <p>
76 * An <code>AttachmentPart</code> object is created with the method
77 * <code>SOAPMessage.createAttachmentPart</code>. After setting its MIME headers,
78 * the <code>AttachmentPart</code> object is added to the message
79 * that created it with the method <code>SOAPMessage.addAttachmentPart</code>.
80 *
81 * <p>
82 * The following code fragment, in which <code>m</code> is a
83 * <code>SOAPMessage</code> object and <code>contentStringl</code> is a
84 * <code>String</code>, creates an instance of <code>AttachmentPart</code>,
85 * sets the <code>AttachmentPart</code> object with some content and
86 * header information, and adds the <code>AttachmentPart</code> object to
87 * the <code>SOAPMessage</code> object.
88 * <PRE>
89 * AttachmentPart ap1 = m.createAttachmentPart();
90 * ap1.setContent(contentString1, "text/plain");
91 * m.addAttachmentPart(ap1);
92 * </PRE>
93 *
94 *
95 * <p>
96 * The following code fragment creates and adds a second
97 * <code>AttachmentPart</code> instance to the same message. <code>jpegData</code>
98 * is a binary byte buffer representing the jpeg file.
99 * <PRE>
100 * AttachmentPart ap2 = m.createAttachmentPart();
101 * byte[] jpegData = ...;
102 * ap2.setContent(new ByteArrayInputStream(jpegData), "image/jpeg");
103 * m.addAttachmentPart(ap2);
104 * </PRE>
105 * <p>
106 * The <code>getContent</code> method retrieves the contents and header from
107 * an <code>AttachmentPart</code> object. Depending on the
108 * <code>DataContentHandler</code> objects present, the returned
109 * <code>Object</code> can either be a typed Java object corresponding
110 * to the MIME type or an <code>InputStream</code> object that contains the
111 * content as bytes.
112 * <PRE>
113 * String content1 = ap1.getContent();
114 * java.io.InputStream content2 = ap2.getContent();
115 * </PRE>
116 *
117 * The method <code>clearContent</code> removes all the content from an
118 * <code>AttachmentPart</code> object but does not affect its header information.
119 * <PRE>
120 * ap1.clearContent();
121 * </PRE>
122 */
123
124 public abstract class AttachmentPart {
125 /**
126 * Returns the number of bytes in this <code>AttachmentPart</code>
127 * object.
128 *
129 * @return the size of this <code>AttachmentPart</code> object in bytes
130 * or -1 if the size cannot be determined
131 * @exception SOAPException if the content of this attachment is
132 * corrupted of if there was an exception while trying
133 * to determine the size.
134 */
135 public abstract int getSize() throws SOAPException;
136
137 /**
138 * Clears out the content of this <code>AttachmentPart</code> object.
139 * The MIME header portion is left untouched.
140 */
141 public abstract void clearContent();
142
143 /**
144 * Gets the content of this <code>AttachmentPart</code> object as a Java
145 * object. The type of the returned Java object depends on (1) the
146 * <code>DataContentHandler</code> object that is used to interpret the bytes
147 * and (2) the <code>Content-Type</code> given in the header.
148 * <p>
149 * For the MIME content types "text/plain", "text/html" and "text/xml", the
150 * <code>DataContentHandler</code> object does the conversions to and
151 * from the Java types corresponding to the MIME types.
152 * For other MIME types,the <code>DataContentHandler</code> object
153 * can return an <code>InputStream</code> object that contains the content data
154 * as raw bytes.
155 * <p>
156 * A SAAJ-compliant implementation must, as a minimum, return a
157 * <code>java.lang.String</code> object corresponding to any content
158 * stream with a <code>Content-Type</code> value of
159 * <code>text/plain</code>, a
160 * <code>javax.xml.transform.stream.StreamSource</code> object corresponding to a
161 * content stream with a <code>Content-Type</code> value of
162 * <code>text/xml</code>, a <code>java.awt.Image</code> object
163 * corresponding to a content stream with a
164 * <code>Content-Type</code> value of <code>image/gif</code> or
165 * <code>image/jpeg</code>. For those content types that an
166 * installed <code>DataContentHandler</code> object does not understand, the
167 * <code>DataContentHandler</code> object is required to return a
168 * <code>java.io.InputStream</code> object with the raw bytes.
169 *
170 * @return a Java object with the content of this <code>AttachmentPart</code>
171 * object
172 *
173 * @exception SOAPException if there is no content set into this
174 * <code>AttachmentPart</code> object or if there was a data
175 * transformation error
176 */
177 public abstract Object getContent() throws SOAPException;
178
179 /**
180 * Gets the content of this <code>AttachmentPart</code> object as an
181 * InputStream as if a call had been made to <code>getContent</code> and no
182 * <code>DataContentHandler</code> had been registered for the
183 * <code>content-type</code> of this <code>AttachmentPart</code>.
184 *<p>
185 * Note that reading from the returned InputStream would result in consuming
186 * the data in the stream. It is the responsibility of the caller to reset
187 * the InputStream appropriately before calling a Subsequent API. If a copy
188 * of the raw attachment content is required then the {@link #getRawContentBytes} API
189 * should be used instead.
190 *
191 * @return an <code>InputStream</code> from which the raw data contained by
192 * the <code>AttachmentPart</code> can be accessed.
193 *
194 * @throws SOAPException if there is no content set into this
195 * <code>AttachmentPart</code> object or if there was a data
196 * transformation error.
197 *
198 * @since SAAJ 1.3
199 * @see #getRawContentBytes
200 */
201 public abstract InputStream getRawContent() throws SOAPException;
202
203 /**
204 * Gets the content of this <code>AttachmentPart</code> object as a
205 * byte[] array as if a call had been made to <code>getContent</code> and no
206 * <code>DataContentHandler</code> had been registered for the
207 * <code>content-type</code> of this <code>AttachmentPart</code>.
208 *
209 * @return a <code>byte[]</code> array containing the raw data of the
210 * <code>AttachmentPart</code>.
211 *
212 * @throws SOAPException if there is no content set into this
213 * <code>AttachmentPart</code> object or if there was a data
214 * transformation error.
215 *
216 * @since SAAJ 1.3
217 */
218 public abstract byte[] getRawContentBytes() throws SOAPException;
219
220 /**
221 * Returns an <code>InputStream</code> which can be used to obtain the
222 * content of <code>AttachmentPart</code> as Base64 encoded
223 * character data, this method would base64 encode the raw bytes
224 * of the attachment and return.
225 *
226 * @return an <code>InputStream</code> from which the Base64 encoded
227 * <code>AttachmentPart</code> can be read.
228 *
229 * @throws SOAPException if there is no content set into this
230 * <code>AttachmentPart</code> object or if there was a data
231 * transformation error.
232 *
233 * @since SAAJ 1.3
234 */
235 public abstract InputStream getBase64Content() throws SOAPException;
236
237 /**
238 * Sets the content of this attachment part to that of the given
239 * <code>Object</code> and sets the value of the <code>Content-Type</code>
240 * header to the given type. The type of the
241 * <code>Object</code> should correspond to the value given for the
242 * <code>Content-Type</code>. This depends on the particular
243 * set of <code>DataContentHandler</code> objects in use.
244 *
245 *
246 * @param object the Java object that makes up the content for
247 * this attachment part
248 * @param contentType the MIME string that specifies the type of
249 * the content
250 *
251 * @exception IllegalArgumentException may be thrown if the contentType
252 * does not match the type of the content object, or if there
253 * was no <code>DataContentHandler</code> object for this
254 * content object
255 *
256 * @see #getContent
257 */
258 public abstract void setContent(Object object, String contentType);
259
260 /**
261 * Sets the content of this attachment part to that contained by the
262 * <code>InputStream</code> <code>content</code> and sets the value of the
263 * <code>Content-Type</code> header to the value contained in
264 * <code>contentType</code>.
265 * <P>
266 * A subsequent call to getSize() may not be an exact measure
267 * of the content size.
268 *
269 * @param content the raw data to add to the attachment part
270 * @param contentType the value to set into the <code>Content-Type</code>
271 * header
272 *
273 * @exception SOAPException if an there is an error in setting the content
274 * @exception NullPointerException if <code>content</code> is null
275 * @since SAAJ 1.3
276 */
277 public abstract void setRawContent(InputStream content, String contentType) throws SOAPException;
278
279 /**
280 * Sets the content of this attachment part to that contained by the
281 * <code>byte[]</code> array <code>content</code> and sets the value of the
282 * <code>Content-Type</code> header to the value contained in
283 * <code>contentType</code>.
284 *
285 * @param content the raw data to add to the attachment part
286 * @param contentType the value to set into the <code>Content-Type</code>
287 * header
288 * @param offset the offset in the byte array of the content
289 * @param len the number of bytes that form the content
290 *
291 * @exception SOAPException if an there is an error in setting the content
292 * or content is null
293 * @since SAAJ 1.3
294 */
295 public abstract void setRawContentBytes(
296 byte[] content, int offset, int len, String contentType)
297 throws SOAPException;
298
299
300 /**
301 * Sets the content of this attachment part from the Base64 source
302 * <code>InputStream</code> and sets the value of the
303 * <code>Content-Type</code> header to the value contained in
304 * <code>contentType</code>, This method would first decode the base64
305 * input and write the resulting raw bytes to the attachment.
306 * <P>
307 * A subsequent call to getSize() may not be an exact measure
308 * of the content size.
309 *
310 * @param content the base64 encoded data to add to the attachment part
311 * @param contentType the value to set into the <code>Content-Type</code>
312 * header
313 *
314 * @exception SOAPException if an there is an error in setting the content
315 * @exception NullPointerException if <code>content</code> is null
316 *
317 * @since SAAJ 1.3
318 */
319 public abstract void setBase64Content(
320 InputStream content, String contentType) throws SOAPException;
321
322
323 /**
324 * Gets the <code>DataHandler</code> object for this <code>AttachmentPart</code>
325 * object.
326 *
327 * @return the <code>DataHandler</code> object associated with this
328 * <code>AttachmentPart</code> object
329 *
330 * @exception SOAPException if there is no data in
331 * this <code>AttachmentPart</code> object
332 */
333 public abstract DataHandler getDataHandler()
334 throws SOAPException;
335
336 /**
337 * Sets the given <code>DataHandler</code> object as the data handler
338 * for this <code>AttachmentPart</code> object. Typically, on an incoming
339 * message, the data handler is automatically set. When
340 * a message is being created and populated with content, the
341 * <code>setDataHandler</code> method can be used to get data from
342 * various data sources into the message.
343 *
344 * @param dataHandler the <code>DataHandler</code> object to be set
345 *
346 * @exception IllegalArgumentException if there was a problem with
347 * the specified <code>DataHandler</code> object
348 */
349 public abstract void setDataHandler(DataHandler dataHandler);
350
351
352 /**
353 * Gets the value of the MIME header whose name is "Content-ID".
354 *
355 * @return a <code>String</code> giving the value of the
356 * "Content-ID" header or <code>null</code> if there
357 * is none
358 * @see #setContentId
359 */
360 public String getContentId() {
361 String[] values = getMimeHeader("Content-ID");
362 if (values != null && values.length > 0)
363 return values[0];
364 return null;
365 }
366
367 /**
368 * Gets the value of the MIME header whose name is "Content-Location".
369 *
370 * @return a <code>String</code> giving the value of the
371 * "Content-Location" header or <code>null</code> if there
372 * is none
373 */
374 public String getContentLocation() {
375 String[] values = getMimeHeader("Content-Location");
376 if (values != null && values.length > 0)
377 return values[0];
378 return null;
379 }
380
381 /**
382 * Gets the value of the MIME header whose name is "Content-Type".
383 *
384 * @return a <code>String</code> giving the value of the
385 * "Content-Type" header or <code>null</code> if there
386 * is none
387 */
388 public String getContentType() {
389 String[] values = getMimeHeader("Content-Type");
390 if (values != null && values.length > 0)
391 return values[0];
392 return null;
393 }
394
395 /**
396 * Sets the MIME header whose name is "Content-ID" with the given value.
397 *
398 * @param contentId a <code>String</code> giving the value of the
399 * "Content-ID" header
400 *
401 * @exception IllegalArgumentException if there was a problem with
402 * the specified <code>contentId</code> value
403 * @see #getContentId
404 */
405 public void setContentId(String contentId)
406 {
407 setMimeHeader("Content-ID", contentId);
408 }
409
410
411 /**
412 * Sets the MIME header whose name is "Content-Location" with the given value.
413 *
414 *
415 * @param contentLocation a <code>String</code> giving the value of the
416 * "Content-Location" header
417 * @exception IllegalArgumentException if there was a problem with
418 * the specified content location
419 */
420 public void setContentLocation(String contentLocation)
421 {
422 setMimeHeader("Content-Location", contentLocation);
423 }
424
425 /**
426 * Sets the MIME header whose name is "Content-Type" with the given value.
427 *
428 * @param contentType a <code>String</code> giving the value of the
429 * "Content-Type" header
430 *
431 * @exception IllegalArgumentException if there was a problem with
432 * the specified content type
433 */
434 public void setContentType(String contentType)
435 {
436 setMimeHeader("Content-Type", contentType);
437 }
438
439 /**
440 * Removes all MIME headers that match the given name.
441 *
442 * @param header the string name of the MIME header/s to
443 * be removed
444 */
445 public abstract void removeMimeHeader(String header);
446
447 /**
448 * Removes all the MIME header entries.
449 */
450 public abstract void removeAllMimeHeaders();
451
452
453 /**
454 * Gets all the values of the header identified by the given
455 * <code>String</code>.
456 *
457 * @param name the name of the header; example: "Content-Type"
458 * @return a <code>String</code> array giving the value for the
459 * specified header
460 * @see #setMimeHeader
461 */
462 public abstract String[] getMimeHeader(String name);
463
464
465 /**
466 * Changes the first header entry that matches the given name
467 * to the given value, adding a new header if no existing header
468 * matches. This method also removes all matching headers but the first. <p>
469 *
470 * Note that RFC822 headers can only contain US-ASCII characters.
471 *
472 * @param name a <code>String</code> giving the name of the header
473 * for which to search
474 * @param value a <code>String</code> giving the value to be set for
475 * the header whose name matches the given name
476 *
477 * @exception IllegalArgumentException if there was a problem with
478 * the specified mime header name or value
479 */
480 public abstract void setMimeHeader(String name, String value);
481
482
483 /**
484 * Adds a MIME header with the specified name and value to this
485 * <code>AttachmentPart</code> object.
486 * <p>
487 * Note that RFC822 headers can contain only US-ASCII characters.
488 *
489 * @param name a <code>String</code> giving the name of the header
490 * to be added
491 * @param value a <code>String</code> giving the value of the header
492 * to be added
493 *
494 * @exception IllegalArgumentException if there was a problem with
495 * the specified mime header name or value
496 */
497 public abstract void addMimeHeader(String name, String value);
498
499 /**
500 * Retrieves all the headers for this <code>AttachmentPart</code> object
501 * as an iterator over the <code>MimeHeader</code> objects.
502 *
503 * @return an <code>Iterator</code> object with all of the Mime
504 * headers for this <code>AttachmentPart</code> object
505 */
506 public abstract Iterator getAllMimeHeaders();
507
508 /**
509 * Retrieves all <code>MimeHeader</code> objects that match a name in
510 * the given array.
511 *
512 * @param names a <code>String</code> array with the name(s) of the
513 * MIME headers to be returned
514 * @return all of the MIME headers that match one of the names in the
515 * given array as an <code>Iterator</code> object
516 */
517 public abstract Iterator getMatchingMimeHeaders(String[] names);
518
519 /**
520 * Retrieves all <code>MimeHeader</code> objects whose name does
521 * not match a name in the given array.
522 *
523 * @param names a <code>String</code> array with the name(s) of the
524 * MIME headers not to be returned
525 * @return all of the MIME headers in this <code>AttachmentPart</code> object
526 * except those that match one of the names in the
527 * given array. The nonmatching MIME headers are returned as an
528 * <code>Iterator</code> object.
529 */
530 public abstract Iterator getNonMatchingMimeHeaders(String[] names);
531 }