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