1 /* 2 * Copyright (c) 2004, 2017, 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.util.Iterator; 30 31 import javax.activation.DataHandler; 32 33 /** 34 * A single attachment to a {@code SOAPMessage} object. A {@code SOAPMessage} 35 * object may contain zero, one, or many {@code AttachmentPart} objects. 36 * Each {@code AttachmentPart} object consists of two parts, 37 * application-specific content and associated MIME headers. The 38 * MIME headers consists of name/value pairs that can be used to 39 * identify and describe the content. 40 * <p> 41 * An {@code AttachmentPart} object must conform to certain standards. 42 * <OL> 43 * <LI>It must conform to <a href="http://www.ietf.org/rfc/rfc2045.txt"> 44 * MIME [RFC2045] standards</a> 45 * <LI>It MUST contain content 46 * <LI>The header portion MUST include the following header: 47 * <UL> 48 * <LI>{@code Content-Type}<br> 49 * This header identifies the type of data in the content of an 50 * {@code AttachmentPart} object and MUST conform to [RFC2045]. 51 * The following is an example of a Content-Type header: 52 * <PRE> 53 * Content-Type: application/xml 54 * </PRE> 55 * The following line of code, in which {@code ap} is an 56 * {@code AttachmentPart} object, sets the header shown in 57 * the previous example. 58 * <PRE> 59 * ap.setMimeHeader("Content-Type", "application/xml"); 60 * </PRE> 61 * </UL> 62 * </OL> 63 * <p> 64 * There are no restrictions on the content portion of an {@code 65 * AttachmentPart} object. The content may be anything from a 66 * simple plain text object to a complex XML document or image file. 67 * 68 * <p> 69 * An {@code AttachmentPart} object is created with the method 70 * {@code SOAPMessage.createAttachmentPart}. After setting its MIME headers, 71 * the {@code AttachmentPart} object is added to the message 72 * that created it with the method {@code SOAPMessage.addAttachmentPart}. 73 * 74 * <p> 75 * The following code fragment, in which {@code m} is a 76 * {@code SOAPMessage} object and {@code contentStringl} is a 77 * {@code String}, creates an instance of {@code AttachmentPart}, 78 * sets the {@code AttachmentPart} object with some content and 79 * header information, and adds the {@code AttachmentPart} object to 80 * the {@code SOAPMessage} object. 81 * <PRE> 82 * AttachmentPart ap1 = m.createAttachmentPart(); 83 * ap1.setContent(contentString1, "text/plain"); 84 * m.addAttachmentPart(ap1); 85 * </PRE> 86 * 87 * 88 * <p> 89 * The following code fragment creates and adds a second 90 * {@code AttachmentPart} instance to the same message. {@code jpegData} 91 * is a binary byte buffer representing the jpeg file. 92 * <PRE> 93 * AttachmentPart ap2 = m.createAttachmentPart(); 94 * byte[] jpegData = ...; 95 * ap2.setContent(new ByteArrayInputStream(jpegData), "image/jpeg"); 96 * m.addAttachmentPart(ap2); 97 * </PRE> 98 * <p> 99 * The {@code getContent} method retrieves the contents and header from 100 * an {@code AttachmentPart} object. Depending on the 101 * {@code DataContentHandler} objects present, the returned 102 * {@code Object} can either be a typed Java object corresponding 103 * to the MIME type or an {@code InputStream} object that contains the 104 * content as bytes. 105 * <PRE> 106 * String content1 = ap1.getContent(); 107 * java.io.InputStream content2 = ap2.getContent(); 108 * </PRE> 109 * 110 * The method {@code clearContent} removes all the content from an 111 * {@code AttachmentPart} object but does not affect its header information. 112 * <PRE> 113 * ap1.clearContent(); 114 * </PRE> 115 * 116 * @since 1.6 117 */ 118 119 public abstract class AttachmentPart { 120 /** 121 * Returns the number of bytes in this {@code AttachmentPart} 122 * object. 123 * 124 * @return the size of this {@code AttachmentPart} 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} 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} object as a Java 140 * object. The type of the returned Java object depends on (1) the 141 * {@code DataContentHandler} object that is used to interpret the bytes 142 * and (2) the {@code Content-Type} given in the header. 143 * <p> 144 * For the MIME content types "text/plain", "text/html" and "text/xml", the 145 * {@code DataContentHandler} object does the conversions to and 146 * from the Java types corresponding to the MIME types. 147 * For other MIME types,the {@code DataContentHandler} object 148 * can return an {@code InputStream} 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} object corresponding to any content 153 * stream with a {@code Content-Type} value of 154 * {@code text/plain}, a 155 * {@code javax.xml.transform.stream.StreamSource} object corresponding to a 156 * content stream with a {@code Content-Type} value of 157 * {@code text/xml}, a {@code java.awt.Image} object 158 * corresponding to a content stream with a 159 * {@code Content-Type} value of {@code image/gif} or 160 * {@code image/jpeg}. For those content types that an 161 * installed {@code DataContentHandler} object does not understand, the 162 * {@code DataContentHandler} object is required to return a 163 * {@code java.io.InputStream} object with the raw bytes. 164 * 165 * @return a Java object with the content of this {@code AttachmentPart} 166 * object 167 * 168 * @exception SOAPException if there is no content set into this 169 * {@code AttachmentPart} 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} object as an 176 * InputStream as if a call had been made to {@code getContent} and no 177 * {@code DataContentHandler} had been registered for the 178 * {@code content-type} of this {@code AttachmentPart}. 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} from which the raw data contained by 187 * the {@code AttachmentPart} can be accessed. 188 * 189 * @throws SOAPException if there is no content set into this 190 * {@code AttachmentPart} object or if there was a data 191 * transformation error. 192 * 193 * @since 1.6, SAAJ 1.3 194 * @see #getRawContentBytes 195 */ 196 public abstract InputStream getRawContent() throws SOAPException; 197 198 /** 199 * Gets the content of this {@code AttachmentPart} object as a 200 * byte[] array as if a call had been made to {@code getContent} and no 201 * {@code DataContentHandler} had been registered for the 202 * {@code content-type} of this {@code AttachmentPart}. 203 * 204 * @return a {@code byte[]} array containing the raw data of the 205 * {@code AttachmentPart}. 206 * 207 * @throws SOAPException if there is no content set into this 208 * {@code AttachmentPart} object or if there was a data 209 * transformation error. 210 * 211 * @since 1.6, SAAJ 1.3 212 */ 213 public abstract byte[] getRawContentBytes() throws SOAPException; 214 215 /** 216 * Returns an {@code InputStream} which can be used to obtain the 217 * content of {@code AttachmentPart} 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} from which the Base64 encoded 222 * {@code AttachmentPart} can be read. 223 * 224 * @throws SOAPException if there is no content set into this 225 * {@code AttachmentPart} object or if there was a data 226 * transformation error. 227 * 228 * @since 1.6, 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} and sets the value of the {@code Content-Type} 235 * header to the given type. The type of the 236 * {@code Object} should correspond to the value given for the 237 * {@code Content-Type}. This depends on the particular 238 * set of {@code DataContentHandler} 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} 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 content} and sets the value of the 258 * {@code Content-Type} header to the value contained in 259 * {@code contentType}. 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} 266 * header 267 * 268 * @exception SOAPException if an there is an error in setting the content 269 * @exception NullPointerException if {@code content} is null 270 * @since 1.6, 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[]} array {@code content} and sets the value of the 277 * {@code Content-Type} header to the value contained in 278 * {@code contentType}. 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} 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 1.6, 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} and sets the value of the 298 * {@code Content-Type} header to the value contained in 299 * {@code contentType}, 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} 307 * header 308 * 309 * @exception SOAPException if an there is an error in setting the content 310 * @exception NullPointerException if {@code content} is null 311 * 312 * @since 1.6, SAAJ 1.3 313 */ 314 public abstract void setBase64Content( 315 InputStream content, String contentType) throws SOAPException; 316 317 318 /** 319 * Gets the {@code DataHandler} object for this {@code AttachmentPart} 320 * object. 321 * 322 * @return the {@code DataHandler} object associated with this 323 * {@code AttachmentPart} object 324 * 325 * @exception SOAPException if there is no data in 326 * this {@code AttachmentPart} object 327 */ 328 public abstract DataHandler getDataHandler() 329 throws SOAPException; 330 331 /** 332 * Sets the given {@code DataHandler} object as the data handler 333 * for this {@code AttachmentPart} 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} method can be used to get data from 337 * various data sources into the message. 338 * 339 * @param dataHandler the {@code DataHandler} object to be set 340 * 341 * @exception IllegalArgumentException if there was a problem with 342 * the specified {@code DataHandler} 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} giving the value of the 351 * "Content-ID" header or {@code null} 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} giving the value of the 366 * "Content-Location" header or {@code null} 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} giving the value of the 380 * "Content-Type" header or {@code null} 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} giving the value of the 394 * "Content-ID" header 395 * 396 * @exception IllegalArgumentException if there was a problem with 397 * the specified {@code contentId} 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} 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} 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}. 451 * 452 * @param name the name of the header; example: "Content-Type" 453 * @return a {@code String} 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} giving the name of the header 468 * for which to search 469 * @param value a {@code String} 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} object. 481 * <p> 482 * Note that RFC822 headers can contain only US-ASCII characters. 483 * 484 * @param name a {@code String} giving the name of the header 485 * to be added 486 * @param value a {@code String} 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} object 496 * as an iterator over the {@code MimeHeader} objects. 497 * 498 * @return an {@code Iterator} object with all of the Mime 499 * headers for this {@code AttachmentPart} object 500 */ 501 public abstract Iterator<MimeHeader> getAllMimeHeaders(); 502 503 /** 504 * Retrieves all {@code MimeHeader} objects that match a name in 505 * the given array. 506 * 507 * @param names a {@code String} 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} object 511 */ 512 public abstract Iterator<MimeHeader> getMatchingMimeHeaders(String[] names); 513 514 /** 515 * Retrieves all {@code MimeHeader} objects whose name does 516 * not match a name in the given array. 517 * 518 * @param names a {@code String} 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} 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} object. 524 */ 525 public abstract Iterator<MimeHeader> getNonMatchingMimeHeaders(String[] names); 526 }