1 /*
   2  * Copyright (c) 2004, 2013, 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  * @since 1.6
 119  */
 120 
 121 public abstract class AttachmentPart {
 122     /**
 123      * Returns the number of bytes in this <code>AttachmentPart</code>
 124      * object.
 125      *
 126      * @return the size of this <code>AttachmentPart</code> object in bytes
 127      *         or -1 if the size cannot be determined
 128      * @exception SOAPException if the content of this attachment is
 129      *            corrupted of if there was an exception while trying
 130      *            to determine the size.
 131      */
 132     public abstract int getSize() throws SOAPException;
 133 
 134     /**
 135      * Clears out the content of this <code>AttachmentPart</code> object.
 136      * The MIME header portion is left untouched.
 137      */
 138     public abstract void clearContent();
 139 
 140     /**
 141      * Gets the content of this <code>AttachmentPart</code> object as a Java
 142      * object. The type of the returned Java object depends on (1) the
 143      * <code>DataContentHandler</code> object that is used to interpret the bytes
 144      * and (2) the <code>Content-Type</code> given in the header.
 145      * <p>
 146      * For the MIME content types "text/plain", "text/html" and "text/xml", the
 147      * <code>DataContentHandler</code> object does the conversions to and
 148      * from the Java types corresponding to the MIME types.
 149      * For other MIME types,the <code>DataContentHandler</code> object
 150      * can return an <code>InputStream</code> object that contains the content data
 151      * as raw bytes.
 152      * <p>
 153      * A SAAJ-compliant implementation must, as a minimum, return a
 154      * <code>java.lang.String</code> object corresponding to any content
 155      * stream with a <code>Content-Type</code> value of
 156      * <code>text/plain</code>, a
 157      * <code>javax.xml.transform.stream.StreamSource</code> object corresponding to a
 158      * content stream with a <code>Content-Type</code> value of
 159      * <code>text/xml</code>, a <code>java.awt.Image</code> object
 160      * corresponding to a content stream with a
 161      * <code>Content-Type</code> value of <code>image/gif</code> or
 162      * <code>image/jpeg</code>.  For those content types that an
 163      * installed <code>DataContentHandler</code> object does not understand, the
 164      * <code>DataContentHandler</code> object is required to return a
 165      * <code>java.io.InputStream</code> object with the raw bytes.
 166      *
 167      * @return a Java object with the content of this <code>AttachmentPart</code>
 168      *         object
 169      *
 170      * @exception SOAPException if there is no content set into this
 171      *            <code>AttachmentPart</code> object or if there was a data
 172      *            transformation error
 173      */
 174     public abstract Object getContent() throws SOAPException;
 175 
 176     /**
 177      * Gets the content of this <code>AttachmentPart</code> object as an
 178      * InputStream as if a call had been made to <code>getContent</code> and no
 179      * <code>DataContentHandler</code> had been registered for the
 180      * <code>content-type</code> of this <code>AttachmentPart</code>.
 181      *<p>
 182      * Note that reading from the returned InputStream would result in consuming
 183      * the data in the stream. It is the responsibility of the caller to reset
 184      * the InputStream appropriately before calling a Subsequent API. If a copy
 185      * of the raw attachment content is required then the {@link #getRawContentBytes} API
 186      * should be used instead.
 187      *
 188      * @return an <code>InputStream</code> from which the raw data contained by
 189      *      the <code>AttachmentPart</code> can be accessed.
 190      *
 191      * @throws SOAPException if there is no content set into this
 192      *      <code>AttachmentPart</code> object or if there was a data
 193      *      transformation error.
 194      *
 195      * @since 1.6, SAAJ 1.3
 196      * @see #getRawContentBytes
 197      */
 198     public abstract InputStream getRawContent() throws SOAPException;
 199 
 200     /**
 201      * Gets the content of this <code>AttachmentPart</code> object as a
 202      * byte[] array as if a call had been made to <code>getContent</code> and no
 203      * <code>DataContentHandler</code> had been registered for the
 204      * <code>content-type</code> of this <code>AttachmentPart</code>.
 205      *
 206      * @return a <code>byte[]</code> array containing the raw data of the
 207      *      <code>AttachmentPart</code>.
 208      *
 209      * @throws SOAPException if there is no content set into this
 210      *      <code>AttachmentPart</code> object or if there was a data
 211      *      transformation error.
 212      *
 213      * @since 1.6, SAAJ 1.3
 214      */
 215     public abstract byte[] getRawContentBytes() throws SOAPException;
 216 
 217     /**
 218      * Returns an <code>InputStream</code> which can be used to obtain the
 219      * content of <code>AttachmentPart</code>  as Base64 encoded
 220      * character data, this method would base64 encode the raw bytes
 221      * of the attachment and return.
 222      *
 223      * @return an <code>InputStream</code> from which the Base64 encoded
 224      *       <code>AttachmentPart</code> can be read.
 225      *
 226      * @throws SOAPException if there is no content set into this
 227      *      <code>AttachmentPart</code> object or if there was a data
 228      *      transformation error.
 229      *
 230      * @since 1.6, SAAJ 1.3
 231      */
 232     public abstract InputStream getBase64Content() throws SOAPException;
 233 
 234     /**
 235      * Sets the content of this attachment part to that of the given
 236      * <code>Object</code> and sets the value of the <code>Content-Type</code>
 237      * header to the given type. The type of the
 238      * <code>Object</code> should correspond to the value given for the
 239      * <code>Content-Type</code>. This depends on the particular
 240      * set of <code>DataContentHandler</code> objects in use.
 241      *
 242      *
 243      * @param object the Java object that makes up the content for
 244      *               this attachment part
 245      * @param contentType the MIME string that specifies the type of
 246      *                  the content
 247      *
 248      * @exception IllegalArgumentException may be thrown if the contentType
 249      *            does not match the type of the content object, or if there
 250      *            was no <code>DataContentHandler</code> object for this
 251      *            content object
 252      *
 253      * @see #getContent
 254      */
 255     public abstract void setContent(Object object, String contentType);
 256 
 257     /**
 258      * Sets the content of this attachment part to that contained by the
 259      * <code>InputStream</code> <code>content</code> and sets the value of the
 260      * <code>Content-Type</code> header to the value contained in
 261      * <code>contentType</code>.
 262      * <P>
 263      *  A subsequent call to getSize() may not be an exact measure
 264      *  of the content size.
 265      *
 266      * @param content the raw data to add to the attachment part
 267      * @param contentType the value to set into the <code>Content-Type</code>
 268      * header
 269      *
 270      * @exception SOAPException if an there is an error in setting the content
 271      * @exception NullPointerException if <code>content</code> is null
 272      * @since 1.6, SAAJ 1.3
 273      */
 274     public abstract void setRawContent(InputStream content, String contentType) throws SOAPException;
 275 
 276     /**
 277      * Sets the content of this attachment part to that contained by the
 278      * <code>byte[]</code> array <code>content</code> and sets the value of the
 279      * <code>Content-Type</code> header to the value contained in
 280      * <code>contentType</code>.
 281      *
 282      * @param content the raw data to add to the attachment part
 283      * @param contentType the value to set into the <code>Content-Type</code>
 284      * header
 285      * @param offset the offset in the byte array of the content
 286      * @param len the number of bytes that form the content
 287      *
 288      * @exception SOAPException if an there is an error in setting the content
 289      * or content is null
 290      * @since 1.6, SAAJ 1.3
 291      */
 292     public abstract void setRawContentBytes(
 293         byte[] content, int offset, int len,  String contentType)
 294         throws SOAPException;
 295 
 296 
 297     /**
 298      * Sets the content of this attachment part from the Base64 source
 299      * <code>InputStream</code>  and sets the value of the
 300      * <code>Content-Type</code> header to the value contained in
 301      * <code>contentType</code>, This method would first decode the base64
 302      * input and write the resulting raw bytes to the attachment.
 303      * <P>
 304      *  A subsequent call to getSize() may not be an exact measure
 305      *  of the content size.
 306      *
 307      * @param content the base64 encoded data to add to the attachment part
 308      * @param contentType the value to set into the <code>Content-Type</code>
 309      * header
 310      *
 311      * @exception SOAPException if an there is an error in setting the content
 312      * @exception NullPointerException if <code>content</code> is null
 313      *
 314      * @since 1.6, SAAJ 1.3
 315      */
 316     public abstract void setBase64Content(
 317         InputStream content, String contentType) throws SOAPException;
 318 
 319 
 320     /**
 321      * Gets the <code>DataHandler</code> object for this <code>AttachmentPart</code>
 322      * object.
 323      *
 324      * @return the <code>DataHandler</code> object associated with this
 325      *         <code>AttachmentPart</code> object
 326      *
 327      * @exception SOAPException if there is no data in
 328      * this <code>AttachmentPart</code> object
 329      */
 330     public abstract DataHandler getDataHandler()
 331         throws SOAPException;
 332 
 333     /**
 334      * Sets the given <code>DataHandler</code> object as the data handler
 335      * for this <code>AttachmentPart</code> object. Typically, on an incoming
 336      * message, the data handler is automatically set. When
 337      * a message is being created and populated with content, the
 338      * <code>setDataHandler</code> method can be used to get data from
 339      * various data sources into the message.
 340      *
 341      * @param dataHandler the <code>DataHandler</code> object to be set
 342      *
 343      * @exception IllegalArgumentException if there was a problem with
 344      *            the specified <code>DataHandler</code> object
 345      */
 346     public abstract void setDataHandler(DataHandler dataHandler);
 347 
 348 
 349     /**
 350      * Gets the value of the MIME header whose name is "Content-ID".
 351      *
 352      * @return a <code>String</code> giving the value of the
 353      *          "Content-ID" header or <code>null</code> if there
 354      *          is none
 355      * @see #setContentId
 356      */
 357     public String getContentId() {
 358         String[] values = getMimeHeader("Content-ID");
 359         if (values != null && values.length > 0)
 360             return values[0];
 361         return null;
 362     }
 363 
 364     /**
 365      * Gets the value of the MIME header whose name is "Content-Location".
 366      *
 367      * @return a <code>String</code> giving the value of the
 368      *          "Content-Location" header or <code>null</code> if there
 369      *          is none
 370      */
 371     public String getContentLocation() {
 372         String[] values = getMimeHeader("Content-Location");
 373         if (values != null && values.length > 0)
 374             return values[0];
 375         return null;
 376     }
 377 
 378     /**
 379      * Gets the value of the MIME header whose name is "Content-Type".
 380      *
 381      * @return a <code>String</code> giving the value of the
 382      *          "Content-Type" header or <code>null</code> if there
 383      *          is none
 384      */
 385     public String getContentType() {
 386         String[] values = getMimeHeader("Content-Type");
 387         if (values != null && values.length > 0)
 388             return values[0];
 389         return null;
 390     }
 391 
 392     /**
 393      * Sets the MIME header whose name is "Content-ID" with the given value.
 394      *
 395      * @param contentId a <code>String</code> giving the value of the
 396      *          "Content-ID" header
 397      *
 398      * @exception IllegalArgumentException if there was a problem with
 399      *            the specified <code>contentId</code> value
 400      * @see #getContentId
 401      */
 402     public void setContentId(String contentId)
 403     {
 404         setMimeHeader("Content-ID", contentId);
 405     }
 406 
 407 
 408     /**
 409      * Sets the MIME header whose name is "Content-Location" with the given value.
 410      *
 411      *
 412      * @param contentLocation a <code>String</code> giving the value of the
 413      *          "Content-Location" header
 414      * @exception IllegalArgumentException if there was a problem with
 415      *            the specified content location
 416      */
 417     public void setContentLocation(String contentLocation)
 418     {
 419         setMimeHeader("Content-Location", contentLocation);
 420     }
 421 
 422     /**
 423      * Sets the MIME header whose name is "Content-Type" with the given value.
 424      *
 425      * @param contentType a <code>String</code> giving the value of the
 426      *          "Content-Type" header
 427      *
 428      * @exception IllegalArgumentException if there was a problem with
 429      *            the specified content type
 430      */
 431     public void setContentType(String contentType)
 432     {
 433         setMimeHeader("Content-Type", contentType);
 434     }
 435 
 436     /**
 437      * Removes all MIME headers that match the given name.
 438      *
 439      * @param header the string name of the MIME header/s to
 440      *               be removed
 441      */
 442     public abstract void removeMimeHeader(String header);
 443 
 444     /**
 445      * Removes all the MIME header entries.
 446      */
 447     public abstract void removeAllMimeHeaders();
 448 
 449 
 450     /**
 451      * Gets all the values of the header identified by the given
 452      * <code>String</code>.
 453      *
 454      * @param name the name of the header; example: "Content-Type"
 455      * @return a <code>String</code> array giving the value for the
 456      *         specified header
 457      * @see #setMimeHeader
 458      */
 459     public abstract String[] getMimeHeader(String name);
 460 
 461 
 462     /**
 463      * Changes the first header entry that matches the given name
 464      * to the given value, adding a new header if no existing header
 465      * matches. This method also removes all matching headers but the first. <p>
 466      *
 467      * Note that RFC822 headers can only contain US-ASCII characters.
 468      *
 469      * @param   name    a <code>String</code> giving the name of the header
 470      *                  for which to search
 471      * @param   value   a <code>String</code> giving the value to be set for
 472      *                  the header whose name matches the given name
 473      *
 474      * @exception IllegalArgumentException if there was a problem with
 475      *            the specified mime header name or value
 476      */
 477     public abstract void setMimeHeader(String name, String value);
 478 
 479 
 480     /**
 481      * Adds a MIME header with the specified name and value to this
 482      * <code>AttachmentPart</code> object.
 483      * <p>
 484      * Note that RFC822 headers can contain only US-ASCII characters.
 485      *
 486      * @param   name    a <code>String</code> giving the name of the header
 487      *                  to be added
 488      * @param   value   a <code>String</code> giving the value of the header
 489      *                  to be added
 490      *
 491      * @exception IllegalArgumentException if there was a problem with
 492      *            the specified mime header name or value
 493      */
 494     public abstract void addMimeHeader(String name, String value);
 495 
 496     /**
 497      * Retrieves all the headers for this <code>AttachmentPart</code> object
 498      * as an iterator over the <code>MimeHeader</code> objects.
 499      *
 500      * @return  an <code>Iterator</code> object with all of the Mime
 501      *          headers for this <code>AttachmentPart</code> object
 502      */
 503     public abstract Iterator getAllMimeHeaders();
 504 
 505     /**
 506      * Retrieves all <code>MimeHeader</code> objects that match a name in
 507      * the given array.
 508      *
 509      * @param names a <code>String</code> array with the name(s) of the
 510      *        MIME headers to be returned
 511      * @return  all of the MIME headers that match one of the names in the
 512      *           given array as an <code>Iterator</code> object
 513      */
 514     public abstract Iterator getMatchingMimeHeaders(String[] names);
 515 
 516     /**
 517      * Retrieves all <code>MimeHeader</code> objects whose name does
 518      * not match a name in the given array.
 519      *
 520      * @param names a <code>String</code> array with the name(s) of the
 521      *        MIME headers not to be returned
 522      * @return  all of the MIME headers in this <code>AttachmentPart</code> object
 523      *          except those that match one of the names in the
 524      *           given array.  The nonmatching MIME headers are returned as an
 525      *           <code>Iterator</code> object.
 526      */
 527     public abstract Iterator getNonMatchingMimeHeaders(String[] names);
 528 }