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 }