001 /* 002 * Copyright 2001-2004 The Apache Software Foundation. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package javax.xml.soap; 017 018 import javax.activation.DataHandler; 019 import java.util.Iterator; 020 021 /** 022 * <P>A single attachment to a <CODE>SOAPMessage</CODE> object. A 023 * <CODE>SOAPMessage</CODE> object may contain zero, one, or many 024 * <CODE>AttachmentPart</CODE> objects. Each <CODE> 025 * AttachmentPart</CODE> object consists of two parts, 026 * application-specific content and associated MIME headers. The 027 * MIME headers consists of name/value pairs that can be used to 028 * identify and describe the content.</P> 029 * 030 * <P>An <CODE>AttachmentPart</CODE> object must conform to 031 * certain standards.</P> 032 * 033 * <OL> 034 * <LI>It must conform to <A href= 035 * "http://www.ietf.org/rfc/rfc2045.txt">MIME [RFC2045] 036 * standards</A></LI> 037 * 038 * <LI>It MUST contain content</LI> 039 * 040 * <LI> 041 * The header portion MUST include the following header: 042 * 043 * <UL> 044 * <LI> 045 * <CODE>Content-Type</CODE><BR> 046 * This header identifies the type of data in the content 047 * of an <CODE>AttachmentPart</CODE> object and MUST 048 * conform to [RFC2045]. The following is an example of a 049 * Content-Type header: 050 * <PRE> 051 * Content-Type: application/xml 052 * 053 * </PRE> 054 * The following line of code, in which <CODE>ap</CODE> is 055 * an <CODE>AttachmentPart</CODE> object, sets the header 056 * shown in the previous example. 057 * <PRE> 058 * ap.setMimeHeader("Content-Type", "application/xml"); 059 * 060 * </PRE> 061 * 062 * <P></P> 063 * </LI> 064 * </UL> 065 * </LI> 066 * </OL> 067 * 068 * <P>There are no restrictions on the content portion of an 069 * <CODE>AttachmentPart</CODE> object. The content may be anything 070 * from a simple plain text object to a complex XML document or 071 * image file.</P> 072 * 073 * <P>An <CODE>AttachmentPart</CODE> object is created with the 074 * method <CODE>SOAPMessage.createAttachmentPart</CODE>. After 075 * setting its MIME headers, the <CODE>AttachmentPart</CODE> 076 * object is added to the message that created it with the method 077 * <CODE>SOAPMessage.addAttachmentPart</CODE>.</P> 078 * 079 * <P>The following code fragment, in which <CODE>m</CODE> is a 080 * <CODE>SOAPMessage</CODE> object and <CODE>contentStringl</CODE> 081 * is a <CODE>String</CODE>, creates an instance of <CODE> 082 * AttachmentPart</CODE>, sets the <CODE>AttachmentPart</CODE> 083 * object with some content and header information, and adds the 084 * <CODE>AttachmentPart</CODE> object to the <CODE> 085 * SOAPMessage</CODE> object.</P> 086 * <PRE> 087 * AttachmentPart ap1 = m.createAttachmentPart(); 088 * ap1.setContent(contentString1, "text/plain"); 089 * m.addAttachmentPart(ap1); 090 * </PRE> 091 * 092 * <P>The following code fragment creates and adds a second <CODE> 093 * AttachmentPart</CODE> instance to the same message. <CODE> 094 * jpegData</CODE> is a binary byte buffer representing the jpeg 095 * file.</P> 096 * <PRE> 097 * AttachmentPart ap2 = m.createAttachmentPart(); 098 * byte[] jpegData = ...; 099 * ap2.setContent(new ByteArrayInputStream(jpegData), "image/jpeg"); 100 * m.addAttachmentPart(ap2); 101 * </PRE> 102 * 103 * <P>The <CODE>getContent</CODE> method retrieves the contents 104 * and header from an <CODE>AttachmentPart</CODE> object. 105 * Depending on the <CODE>DataContentHandler</CODE> objects 106 * present, the returned <CODE>Object</CODE> can either be a typed 107 * Java object corresponding to the MIME type or an <CODE> 108 * InputStream</CODE> object that contains the content as 109 * bytes.</P> 110 * <PRE> 111 * String content1 = ap1.getContent(); 112 * java.io.InputStream content2 = ap2.getContent(); 113 * </PRE> 114 * The method <CODE>clearContent</CODE> removes all the content 115 * from an <CODE>AttachmentPart</CODE> object but does not affect 116 * its header information. 117 * <PRE> 118 * ap1.clearContent(); 119 * </PRE> 120 */ 121 public abstract class AttachmentPart { 122 123 // fixme: should this constructor be protected? 124 /** Create a new AttachmentPart. */ 125 public AttachmentPart() {} 126 127 /** 128 * Returns the number of bytes in this <CODE> 129 * AttachmentPart</CODE> object. 130 * @return the size of this <CODE>AttachmentPart</CODE> object 131 * in bytes or -1 if the size cannot be determined 132 * @throws SOAPException if the content of this 133 * attachment is corrupted of if there was an exception 134 * while trying to determine the size. 135 */ 136 public abstract int getSize() throws SOAPException; 137 138 /** 139 * Clears out the content of this <CODE> 140 * AttachmentPart</CODE> object. The MIME header portion is left 141 * untouched. 142 */ 143 public abstract void clearContent(); 144 145 /** 146 * Gets the content of this <code>AttachmentPart</code> object as a Java 147 * object. The type of the returned Java object depends on (1) the 148 * <code>DataContentHandler</code> object that is used to interpret the bytes 149 * and (2) the <code>Content-Type</code> given in the header. 150 * <p> 151 * For the MIME content types "text/plain", "text/html" and "text/xml", the 152 * <code>DataContentHandler</code> object does the conversions to and 153 * from the Java types corresponding to the MIME types. 154 * For other MIME types,the <code>DataContentHandler</code> object 155 * can return an <code>InputStream</code> object that contains the content data 156 * as raw bytes. 157 * <p> 158 * A JAXM-compliant implementation must, as a minimum, return a 159 * <code>java.lang.String</code> object corresponding to any content 160 * stream with a <code>Content-Type</code> value of 161 * <code>text/plain</code>, a 162 * <code>javax.xml.transform.StreamSource</code> object corresponding to a 163 * content stream with a <code>Content-Type</code> value of 164 * <code>text/xml</code>, a <code>java.awt.Image</code> object 165 * corresponding to a content stream with a 166 * <code>Content-Type</code> value of <code>image/gif</code> or 167 * <code>image/jpeg</code>. For those content types that an 168 * installed <code>DataContentHandler</code> object does not understand, the 169 * <code>DataContentHandler</code> object is required to return a 170 * <code>java.io.InputStream</code> object with the raw bytes. 171 * 172 * @return a Java object with the content of this <CODE> 173 * AttachmentPart</CODE> object 174 * @throws SOAPException if there is no content set 175 * into this <CODE>AttachmentPart</CODE> object or if there 176 * was a data transformation error 177 */ 178 public abstract Object getContent() throws SOAPException; 179 180 /** 181 * Sets the content of this attachment part to that of the 182 * given <CODE>Object</CODE> and sets the value of the <CODE> 183 * Content-Type</CODE> header to the given type. The type of the 184 * <CODE>Object</CODE> should correspond to the value given for 185 * the <CODE>Content-Type</CODE>. This depends on the particular 186 * set of <CODE>DataContentHandler</CODE> objects in use. 187 * @param object the Java object that makes up 188 * the content for this attachment part 189 * @param contentType the MIME string that 190 * specifies the type of the content 191 * @throws java.lang.IllegalArgumentException if 192 * the contentType does not match the type of the content 193 * object, or if there was no <CODE> 194 * DataContentHandler</CODE> object for this content 195 * object 196 * @see #getContent() getContent() 197 */ 198 public abstract void setContent(Object object, String contentType); 199 200 /** 201 * Gets the <CODE>DataHandler</CODE> object for this <CODE> 202 * AttachmentPart</CODE> object. 203 * @return the <CODE>DataHandler</CODE> object associated with 204 * this <CODE>AttachmentPart</CODE> object 205 * @throws SOAPException if there is 206 * no data in this <CODE>AttachmentPart</CODE> object 207 */ 208 public abstract DataHandler getDataHandler() throws SOAPException; 209 210 /** 211 * Sets the given <CODE>DataHandler</CODE> object as the 212 * data handler for this <CODE>AttachmentPart</CODE> object. 213 * Typically, on an incoming message, the data handler is 214 * automatically set. When a message is being created and 215 * populated with content, the <CODE>setDataHandler</CODE> 216 * method can be used to get data from various data sources into 217 * the message. 218 * @param datahandler <CODE>DataHandler</CODE> object to 219 * be set 220 * @throws java.lang.IllegalArgumentException if 221 * there was a problem with the specified <CODE> 222 * DataHandler</CODE> object 223 */ 224 public abstract void setDataHandler(DataHandler datahandler); 225 226 /** 227 * Gets the value of the MIME header whose name is 228 * "Content-Id". 229 * @return a <CODE>String</CODE> giving the value of the 230 * "Content-Id" header or <CODE>null</CODE> if there is 231 * none 232 * @see #setContentId(java.lang.String) setContentId(java.lang.String) 233 */ 234 public String getContentId() { 235 236 String as[] = getMimeHeader("Content-Id"); 237 238 if (as != null && as.length > 0) { 239 return as[0]; 240 } else { 241 return null; 242 } 243 } 244 245 /** 246 * Gets the value of the MIME header 247 * "Content-Location". 248 * @return a <CODE>String</CODE> giving the value of the 249 * "Content-Location" header or <CODE>null</CODE> if there 250 * is none 251 */ 252 public String getContentLocation() { 253 254 String as[] = getMimeHeader("Content-Location"); 255 256 if (as != null && as.length > 0) { 257 return as[0]; 258 } else { 259 return null; 260 } 261 } 262 263 /** 264 * Gets the value of the MIME header "Content-Type". 265 * @return a <CODE>String</CODE> giving the value of the 266 * "Content-Type" header or <CODE>null</CODE> if there is 267 * none 268 */ 269 public String getContentType() { 270 271 String as[] = getMimeHeader("Content-Type"); 272 273 if (as != null && as.length > 0) { 274 return as[0]; 275 } else { 276 return null; 277 } 278 } 279 280 /** 281 * Sets the MIME header "Content-Id" with the given 282 * value. 283 * @param contentId a <CODE>String</CODE> giving 284 * the value of the "Content-Id" header 285 * @throws java.lang.IllegalArgumentException if 286 * there was a problem with the specified <CODE> 287 * contentId</CODE> value 288 * @see #getContentId() getContentId() 289 */ 290 public void setContentId(String contentId) { 291 setMimeHeader("Content-Id", contentId); 292 } 293 294 /** 295 * Sets the MIME header "Content-Location" with the given 296 * value. 297 * @param contentLocation a <CODE>String</CODE> 298 * giving the value of the "Content-Location" header 299 * @throws java.lang.IllegalArgumentException if 300 * there was a problem with the specified content 301 * location 302 */ 303 public void setContentLocation(String contentLocation) { 304 setMimeHeader("Content-Location", contentLocation); 305 } 306 307 /** 308 * Sets the MIME header "Content-Type" with the given 309 * value. 310 * @param contentType a <CODE>String</CODE> 311 * giving the value of the "Content-Type" header 312 * @throws java.lang.IllegalArgumentException if 313 * there was a problem with the specified content type 314 */ 315 public void setContentType(String contentType) { 316 setMimeHeader("Content-Type", contentType); 317 } 318 319 /** 320 * Removes all MIME headers that match the given name. 321 * @param header - the string name of the MIME 322 * header/s to be removed 323 */ 324 public abstract void removeMimeHeader(String header); 325 326 /** Removes all the MIME header entries. */ 327 public abstract void removeAllMimeHeaders(); 328 329 /** 330 * Gets all the values of the header identified by the given 331 * <CODE>String</CODE>. 332 * @param name the name of the header; example: 333 * "Content-Type" 334 * @return a <CODE>String</CODE> array giving the value for the 335 * specified header 336 * @see #setMimeHeader(java.lang.String, java.lang.String) setMimeHeader(java.lang.String, java.lang.String) 337 */ 338 public abstract String[] getMimeHeader(String name); 339 340 /** 341 * Changes the first header entry that matches the given name 342 * to the given value, adding a new header if no existing 343 * header matches. This method also removes all matching 344 * headers but the first. 345 * 346 * <P>Note that RFC822 headers can only contain US-ASCII 347 * characters.</P> 348 * @param name a <CODE>String</CODE> giving the 349 * name of the header for which to search 350 * @param value a <CODE>String</CODE> giving the 351 * value to be set for the header whose name matches the 352 * given name 353 * @throws java.lang.IllegalArgumentException if 354 * there was a problem with the specified mime header name 355 * or value 356 */ 357 public abstract void setMimeHeader(String name, String value); 358 359 /** 360 * Adds a MIME header with the specified name and value to 361 * this <CODE>AttachmentPart</CODE> object. 362 * 363 * <P>Note that RFC822 headers can contain only US-ASCII 364 * characters.</P> 365 * @param name a <CODE>String</CODE> giving the 366 * name of the header to be added 367 * @param value a <CODE>String</CODE> giving the 368 * value of the header to be added 369 * @throws java.lang.IllegalArgumentException if 370 * there was a problem with the specified mime header name 371 * or value 372 */ 373 public abstract void addMimeHeader(String name, String value); 374 375 /** 376 * Retrieves all the headers for this <CODE> 377 * AttachmentPart</CODE> object as an iterator over the <CODE> 378 * MimeHeader</CODE> objects. 379 * @return an <CODE>Iterator</CODE> object with all of the Mime 380 * headers for this <CODE>AttachmentPart</CODE> object 381 */ 382 public abstract Iterator getAllMimeHeaders(); 383 384 /** 385 * Retrieves all <CODE>MimeHeader</CODE> objects that match 386 * a name in the given array. 387 * @param names a <CODE>String</CODE> array with 388 * the name(s) of the MIME headers to be returned 389 * @return all of the MIME headers that match one of the names 390 * in the given array as an <CODE>Iterator</CODE> 391 * object 392 */ 393 public abstract Iterator getMatchingMimeHeaders(String names[]); 394 395 /** 396 * Retrieves all <CODE>MimeHeader</CODE> objects whose name 397 * does not match a name in the given array. 398 * @param names a <CODE>String</CODE> array with 399 * the name(s) of the MIME headers not to be returned 400 * @return all of the MIME headers in this <CODE> 401 * AttachmentPart</CODE> object except those that match one 402 * of the names in the given array. The nonmatching MIME 403 * headers are returned as an <CODE>Iterator</CODE> 404 * object. 405 */ 406 public abstract Iterator getNonMatchingMimeHeaders(String names[]); 407 }