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