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