Source code: org/apache/axis/Message.java
1 /*
2 * Copyright 2001-2004 The Apache Software Foundation.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package org.apache.axis;
18
19 import org.apache.axis.attachments.Attachments;
20 import org.apache.axis.components.logger.LogFactory;
21 import org.apache.axis.message.SOAPEnvelope;
22 import org.apache.axis.message.MimeHeaders;
23 import org.apache.axis.soap.SOAPConstants;
24 import org.apache.axis.transport.http.HTTPConstants;
25 import org.apache.axis.utils.ClassUtils;
26 import org.apache.axis.utils.Messages;
27 import org.apache.axis.utils.XMLUtils;
28 import org.apache.commons.logging.Log;
29
30 import javax.xml.soap.AttachmentPart;
31 import javax.xml.soap.SOAPException;
32 import javax.xml.soap.SOAPBody;
33 import javax.xml.soap.SOAPHeader;
34 import javax.xml.soap.SOAPMessage;
35
36 import java.io.IOException;
37 import java.lang.reflect.Constructor;
38 import java.lang.reflect.InvocationTargetException;
39 import java.util.Iterator;
40 import java.util.Collections;
41
42 /**
43 * A complete SOAP (and/or XML-RPC, eventually) message.
44 * Includes both the root part (as a SOAPPart), and zero or
45 * more MIME attachments (as AttachmentParts).
46 * <p>
47 * Eventually should be refactored to generalize SOAPPart
48 * for multiple protocols (XML-RPC?).
49 *
50 * @author Rob Jellinghaus (robj@unrealities.com)
51 * @author Doug Davis (dug@us.ibm.com)
52 * @author Glen Daniels (gdaniels@allaire.com)
53 * @author Rick Rineholt
54 * @author Heejune Ahn (cityboy@tmax.co.kr)
55 */
56 public class Message extends javax.xml.soap.SOAPMessage
57 implements java.io.Serializable {
58
59 /**
60 * The <code>Log</code> that this class uses for logging all messages.
61 */
62 protected static Log log =
63 LogFactory.getLog(Message.class.getName());
64
65 /** Message is a request. */
66 public static final String REQUEST = "request";
67
68 /** Message is a a response. */
69 public static final String RESPONSE = "response";
70
71 /** MIME parts defined for messages. */
72 public static final String MIME_MULTIPART_RELATED = "multipart/related";
73
74 /** DIME parts defined for messages. */
75 public static final String MIME_APPLICATION_DIME = "application/dime";
76
77 /** Default Attachments Implementation class. */
78 public static final String DEFAULT_ATTACHMNET_IMPL="org.apache.axis.attachments.AttachmentsImpl";
79
80 /** Current Attachment implementation. */
81 private static String mAttachmentsImplClassName=DEFAULT_ATTACHMNET_IMPL;
82
83 /** Look at the input stream to find the headers to decide the mime type. */
84 public static final String MIME_UNKNOWN = " ";
85
86 // fixme: is this constrained to two values - request/response (e.g.
87 // REQUEST and RESPONSE)? If so, this needs documenting in the get/set
88 // methods and/or converting into a type-safe e-num. Potentially get/set
89 // methods should check these values & throw IllegalArgumentException
90 /**
91 * The messageType indicates whether this is request or response.
92 */
93 private String messageType;
94
95 /**
96 * This Message's SOAPPart. Will always be here.
97 */
98 private SOAPPart mSOAPPart;
99
100 /**
101 * This Message's Attachments object, which manages the attachments
102 * contained in this Message.
103 */
104 private Attachments mAttachments = null;
105
106 private MimeHeaders headers;
107
108 private boolean saveRequired = true;
109
110 /**
111 * Returns the name of the class prividing Attachment Implementation.
112 *
113 * @return class name
114 */
115 public static String getAttachmentImplClassName(){
116 return mAttachmentsImplClassName;
117 }
118
119 private MessageContext msgContext;
120
121 /**
122 * Get the message type.
123 *
124 * @return the message type <code>String</code>
125 */
126 public String getMessageType() {
127 return messageType;
128 }
129
130 /**
131 * Set the message type.
132 *
133 * @param messageType the message type <code>String</code>
134 */
135 public void setMessageType(String messageType) {
136 this.messageType = messageType;
137 }
138
139 /**
140 * Get the context associated with this message.
141 *
142 * @return the message context for this message
143 */
144 public MessageContext getMessageContext() {
145 return msgContext;
146 }
147
148 /**
149 * Set the context associated with this message.
150 *
151 * @param msgContext the message context for this message
152 */
153 public void setMessageContext(MessageContext msgContext) {
154 this.msgContext = msgContext;
155 }
156
157 /**
158 * Construct a Message, using the provided initialContents as the
159 * contents of the Message's SOAPPart.
160 * <p>
161 * Eventually, genericize this to
162 * return the RootPart instead, which will have some kind of
163 * EnvelopeFactory to enable support for things other than SOAP.
164 * But that all will come later, with lots of additional refactoring.
165 *
166 * @param initialContents may be String, byte[], InputStream, SOAPEnvelope,
167 * or AxisFault.
168 * @param bodyInStream is true if initialContents is an InputStream
169 * containing just the SOAP body (no SOAP-ENV).
170 */
171 public Message(Object initialContents, boolean bodyInStream) {
172 setup(initialContents, bodyInStream, null, null, null);
173 }
174
175 /**
176 * Construct a Message, using the provided initialContents as the
177 * contents of the Message's SOAPPart.
178 * <p>
179 * Eventually, genericize this to
180 * return the RootPart instead, which will have some kind of
181 * EnvelopeFactory to enable support for things other than SOAP.
182 * But that all will come later, with lots of additional refactoring.
183 *
184 * @param initialContents may be String, byte[], InputStream, SOAPEnvelope,
185 * or AxisFault.
186 * @param bodyInStream is true if initialContents is an InputStream
187 * containing just the SOAP body (no SOAP-ENV).
188 * @param headers Mime Headers.
189 */
190 public Message(Object initialContents, boolean bodyInStream, javax.xml.soap.MimeHeaders headers) {
191 setup(initialContents, bodyInStream, null, null, headers);
192 }
193
194 /**
195 * Construct a Message, using the provided initialContents as the
196 * contents of the Message's SOAPPart.
197 * <p>
198 * Eventually, genericize this to
199 * return the RootPart instead, which will have some kind of
200 * EnvelopeFactory to enable support for things other than SOAP.
201 * But that all will come later, with lots of additional refactoring.
202 *
203 * @param initialContents may be String, byte[], InputStream, SOAPEnvelope,
204 * or AxisFault.
205 * @param headers Mime Headers.
206 */
207 public Message(Object initialContents, MimeHeaders headers) {
208 setup(initialContents, true, null, null, headers);
209 }
210
211 /**
212 * Construct a Message, using the provided initialContents as the
213 * contents of the Message's SOAPPart.
214 * <p>
215 * Eventually, genericize this to
216 * return the RootPart instead, which will have some kind of
217 * EnvelopeFactory to enable support for things other than SOAP.
218 * But that all will come later, with lots of additional refactoring.
219 *
220 * @param initialContents may be String, byte[], InputStream, SOAPEnvelope,
221 * or AxisFault
222 * @param bodyInStream is true if initialContents is an InputStream
223 * containing just the SOAP body (no SOAP-ENV)
224 * @param contentType this if the contentType has been already determined
225 * (as in the case of servlets)
226 * @param contentLocation the location of the content
227 */
228 public Message(Object initialContents,
229 boolean bodyInStream,
230 String contentType,
231 String contentLocation) {
232 setup(initialContents, bodyInStream, contentType, contentLocation, null);
233 }
234
235 /**
236 * Construct a Message. An overload of Message(Object, boolean),
237 * defaulting bodyInStream to false.
238 *
239 * @param initialContents may be String, byte[], InputStream, SOAPEnvelope,
240 * or AxisFault
241 */
242 public Message(Object initialContents) {
243 setup(initialContents, false, null, null, null);
244 }
245
246 private static Class attachImpl = null;
247
248 //aviod testing and possibly failing everytime.
249 private static boolean checkForAttachmentSupport = true;
250
251 private static boolean attachmentSupportEnabled = false;
252
253 private static synchronized boolean isAttachmentSupportEnabled(MessageContext mc) {
254 if (checkForAttachmentSupport) {
255 //aviod testing and possibly failing everytime.
256 checkForAttachmentSupport = false;
257 try {
258 String attachImpName= AxisEngine.DEFAULT_ATTACHMENT_IMPL;
259 if(null != mc){
260 AxisEngine ae= mc.getAxisEngine();
261 if(null != ae){
262 attachImpName= (String)ae.getOption(
263 AxisEngine.PROP_ATTACHMENT_IMPLEMENTATION);
264 }
265 }
266 if(null == attachImpName){
267 attachImpName=AxisEngine.DEFAULT_ATTACHMENT_IMPL;
268 }
269
270 /**
271 * Attempt to resolve class name, verify that these are present...
272 */
273 ClassUtils.forName("javax.activation.DataHandler");
274 ClassUtils.forName("javax.mail.internet.MimeMultipart");
275
276 attachImpl = ClassUtils.forName(attachImpName);
277
278 attachmentSupportEnabled = true;
279 } catch (ClassNotFoundException ex) {
280 // no support for it, leave mAttachments null.
281 } catch (java.lang.NoClassDefFoundError ex) {
282 // no support for it, leave mAttachments null.
283 }
284 log.debug(Messages.getMessage("attachEnabled") + " " +
285 attachmentSupportEnabled);
286 }
287 return attachmentSupportEnabled;
288 }
289
290 /**
291 * Do the work of construction.
292 *
293 * @param initialContents may be String, byte[], InputStream, SOAPEnvelope,
294 * or AxisFault
295 * @param bodyInStream is true if initialContents is an InputStream
296 * containing just the SOAP body (no SOAP-ENV)
297 * @param contentType this if the contentType has been already determined
298 * (as in the case of servlets)
299 * @param contentLocation the location of the content
300 * @param mimeHeaders mime headers for attachments
301 */
302 private void setup(Object initialContents, boolean bodyInStream,
303 String contentType, String contentLocation,
304 javax.xml.soap.MimeHeaders mimeHeaders) {
305
306 if(contentType == null && mimeHeaders != null) {
307 String contentTypes[] = mimeHeaders.getHeader("Content-Type");
308 contentType = (contentTypes != null)? contentTypes[0] : null;
309 }
310 if(contentLocation == null && mimeHeaders != null) {
311 String contentLocations[] = mimeHeaders.getHeader("Content-Location");
312 contentLocation = (contentLocations != null)? contentLocations[0] : null;
313 }
314 if (contentType != null) {
315 int delimiterIndex = contentType.lastIndexOf("charset");
316 if (delimiterIndex > 0) {
317 String charsetPart = contentType.substring(delimiterIndex);
318 int charsetIndex = charsetPart.indexOf('=');
319 String charset = charsetPart.substring(charsetIndex + 1).trim();
320 if ((charset.startsWith("\"") && charset.endsWith("\""))
321 || (charset.startsWith("'") && charset.endsWith("'"))) {
322 charset = charset.substring(1, charset.length() - 1);
323 }
324 try {
325 setProperty(SOAPMessage.CHARACTER_SET_ENCODING, charset);
326 } catch (SOAPException e) {
327 }
328 }
329 }
330 // Try to construct an AttachmentsImpl object for attachment
331 // functionality.
332 // If there is no org.apache.axis.attachments.AttachmentsImpl class,
333 // it must mean activation.jar is not present and attachments are not
334 // supported.
335 if (isAttachmentSupportEnabled(getMessageContext())) {
336 // Construct one, and cast to Attachments.
337 // There must be exactly one constructor of AttachmentsImpl, which
338 // must take an org.apache.axis.Message!
339 Constructor attachImplConstr = attachImpl.getConstructors()[0];
340 try {
341 mAttachments = (Attachments) attachImplConstr.newInstance(
342 new Object[] { initialContents,
343 contentType, contentLocation});
344
345 //If it can't support it, it wont have a root part.
346 mSOAPPart = (SOAPPart) mAttachments.getRootPart();
347 } catch (InvocationTargetException ex) {
348 log.fatal(Messages.getMessage("invocationTargetException00"),
349 ex);
350 throw new RuntimeException(ex.getMessage());
351 } catch (InstantiationException ex) {
352 log.fatal(Messages.getMessage("instantiationException00"),
353 ex);
354 throw new RuntimeException(ex.getMessage());
355 } catch (IllegalAccessException ex) {
356 log.fatal(Messages.getMessage("illegalAccessException00"),
357 ex);
358 throw new RuntimeException(ex.getMessage());
359 }
360 } else if (contentType != null && contentType.startsWith("multipart")){
361 throw new RuntimeException(Messages.getMessage("noAttachments"));
362 }
363
364 // text/xml
365 if (null == mSOAPPart) {
366 mSOAPPart = new SOAPPart(this, initialContents, bodyInStream);
367 }
368 else
369 mSOAPPart.setMessage(this);
370
371 // The stream was not determined by a more complex type so default to
372 if(mAttachments!=null) mAttachments.setRootPart(mSOAPPart);
373
374 headers = (mimeHeaders == null) ? new MimeHeaders() : new MimeHeaders(mimeHeaders);
375 }
376
377 /**
378 * Get this message's SOAPPart.
379 * <p>
380 * Eventually, this should be generalized beyond just SOAP,
381 * but it's hard to know how to do that without necessitating
382 * a lot of casts in client code. Refactoring keeps getting
383 * easier anyhow.
384 *
385 * @return the soap part of this message
386 */
387 public javax.xml.soap.SOAPPart getSOAPPart() {
388 return mSOAPPart;
389 }
390
391 // fixme: do we realy need this? Can client code not just call
392 // getSOAPPart().getAsString() or is there some future optimization that
393 // could be hooked in here?
394 /**
395 * Get a string representation of this message's SOAPPart.
396 *
397 * @return the soap part of this message as a <code>String</code>
398 * @throws org.apache.axis.AxisFault if the stringification failed
399 */
400 public String getSOAPPartAsString() throws org.apache.axis.AxisFault {
401 return mSOAPPart.getAsString();
402 }
403
404 // fixme: do we realy need this? Can client code not just call
405 // getSOAPPart().getAsBytes() or is there some future optimization that
406 // could be hooked in here?
407 /**
408 * Get a byte array representation of this message's SOAPPart.
409 *
410 * @return the soap part of this message as a <code>byte[]</code>
411 * @throws org.apache.axis.AxisFault if creating the byte[] failed
412 */
413 public byte[] getSOAPPartAsBytes() throws org.apache.axis.AxisFault {
414 return mSOAPPart.getAsBytes();
415 }
416
417 /**
418 * Get this message's SOAPPart as a SOAPEnvelope.
419 *
420 * @return a SOAPEnvelope containing this message's SOAPPart
421 * @throws AxisFault if this failed
422 */
423 public SOAPEnvelope getSOAPEnvelope() throws AxisFault {
424 return mSOAPPart.getAsSOAPEnvelope();
425 }
426
427 /**
428 * Get the Attachments of this Message.
429 * <p>
430 * If this returns null, then NO ATTACHMENT SUPPORT EXISTS in this
431 * configuration of Axis, and no attachment operations may be
432 * performed.
433 *
434 * @return the <code>Attachments</code> if attachments are supported, null
435 * otherwise
436 */
437 public Attachments getAttachmentsImpl() {
438 return mAttachments;
439 }
440
441 /**
442 * Get the content type of the attachments.
443 *
444 * @param sc provides the default content type
445 * @return a <code>String</code> giving the content type of the
446 * attachment
447 * @throws AxisFault if there was an error deducing the content type from
448 * this message
449 */
450 public String getContentType(SOAPConstants sc) throws AxisFault {
451 boolean soap12 = false;
452
453 if(sc != null) {
454 if(sc == SOAPConstants.SOAP12_CONSTANTS) {
455 soap12 = true;
456 }
457 } else {
458 // Support of SOAP 1.2 HTTP binding
459 SOAPEnvelope envelope = getSOAPEnvelope();
460 if (envelope != null) {
461 if (envelope.getSOAPConstants() == SOAPConstants.SOAP12_CONSTANTS) {
462 soap12 = true;
463 }
464 }
465 }
466
467 String encoding = XMLUtils.getEncoding(this, msgContext);;
468 String ret = sc.getContentType() + "; charset=" + encoding.toLowerCase();
469
470 // Support of SOAP 1.2 HTTP binding
471 if (soap12) {
472 ret = HTTPConstants.HEADER_ACCEPT_APPL_SOAP +"; charset=" + encoding;
473 }
474
475 if (getSendType() != Attachments.SEND_TYPE_NONE && mAttachments != null &&
476 0 != mAttachments.getAttachmentCount()) {
477 ret = mAttachments.getContentType();
478 }
479 return ret;
480 }
481
482 private int getSendType() {
483 int sendType = Attachments.SEND_TYPE_NOTSET;
484 if ((msgContext != null) && (msgContext.getService() != null)) {
485 sendType = msgContext.getService().getSendType();
486 }
487 return sendType;
488 }
489
490 //This will have to give way someday to HTTP Chunking but for now kludge.
491 /**
492 * Get the content length, including both soap and any attachments.
493 *
494 * @return the total length of this message in bytes
495 * @throws org.apache.axis.AxisFault if there was a problem that prevented
496 * the length being calculated
497 */
498 public long getContentLength() throws org.apache.axis.AxisFault {
499 long ret = mSOAPPart.getContentLength();
500 if (mAttachments != null && 0 < mAttachments.getAttachmentCount()) {
501 ret = mAttachments.getContentLength();
502 }
503 return ret;
504 }
505
506 /**
507 * Writes this <CODE>SOAPMessage</CODE> object to the given
508 * output stream. The externalization format is as defined by
509 * the SOAP 1.1 with Attachments specification.
510 *
511 * <P>If there are no attachments, just an XML stream is
512 * written out. For those messages that have attachments,
513 * <CODE>writeTo</CODE> writes a MIME-encoded byte stream.</P>
514 * @param os the <CODE>OutputStream</CODE>
515 * object to which this <CODE>SOAPMessage</CODE> object will
516 * be written
517 * @throws SOAPException if there was a problem in
518 * externalizing this SOAP message
519 * @throws IOException if an I/O error
520 * occurs
521 */
522 public void writeTo(java.io.OutputStream os) throws SOAPException, IOException {
523 //Do it the old fashion way.
524 if (getSendType() == Attachments.SEND_TYPE_NONE || mAttachments == null || 0 == mAttachments.getAttachmentCount()) {
525 try {
526 String charEncoding = XMLUtils.getEncoding(this, msgContext);;
527 mSOAPPart.setEncoding(charEncoding);
528 mSOAPPart.writeTo(os);
529 } catch (java.io.IOException e) {
530 log.error(Messages.getMessage("javaIOException00"), e);
531 }
532 } else {
533 try {
534 mAttachments.writeContentToStream(os);
535 } catch (java.lang.Exception e) {
536 log.error(Messages.getMessage("exception00"), e);
537 }
538 }
539 }
540
541 private java.util.Hashtable mProps = new java.util.Hashtable();
542
543 public SOAPBody getSOAPBody() throws SOAPException {
544 return mSOAPPart.getEnvelope().getBody();
545 }
546
547 public SOAPHeader getSOAPHeader() throws SOAPException {
548 return mSOAPPart.getEnvelope().getHeader();
549 }
550
551 public void setProperty(String property, Object value) throws SOAPException {
552 mProps.put(property, value);
553 }
554
555 public Object getProperty(String property) throws SOAPException {
556 return mProps.get(property);
557 }
558
559 /**
560 * Retrieves a description of this <CODE>SOAPMessage</CODE>
561 * object's content.
562 * @return a <CODE>String</CODE> describing the content of this
563 * message or <CODE>null</CODE> if no description has been
564 * set
565 * @see #setContentDescription(java.lang.String) setContentDescription(java.lang.String)
566 */
567 public String getContentDescription() {
568 String values[] = headers.getHeader(HTTPConstants.HEADER_CONTENT_DESCRIPTION);
569 if(values != null && values.length > 0)
570 return values[0];
571 return null;
572 }
573
574 /**
575 * Sets the description of this <CODE>SOAPMessage</CODE>
576 * object's content with the given description.
577 * @param description a <CODE>String</CODE>
578 * describing the content of this message
579 * @see #getContentDescription() getContentDescription()
580 */
581 public void setContentDescription(String description) {
582 headers.setHeader(HTTPConstants.HEADER_CONTENT_DESCRIPTION, description);
583 }
584
585 /**
586 * Updates this <CODE>SOAPMessage</CODE> object with all the
587 * changes that have been made to it. This method is called
588 * automatically when a message is sent or written to by the
589 * methods <CODE>ProviderConnection.send</CODE>, <CODE>
590 * SOAPConnection.call</CODE>, or <CODE>
591 * SOAPMessage.writeTo</CODE>. However, if changes are made to
592 * a message that was received or to one that has already been
593 * sent, the method <CODE>saveChanges</CODE> needs to be
594 * called explicitly in order to save the changes. The method
595 * <CODE>saveChanges</CODE> also generates any changes that
596 * can be read back (for example, a MessageId in profiles that
597 * support a message id). All MIME headers in a message that
598 * is created for sending purposes are guaranteed to have
599 * valid values only after <CODE>saveChanges</CODE> has been
600 * called.
601 *
602 * <P>In addition, this method marks the point at which the
603 * data from all constituent <CODE>AttachmentPart</CODE>
604 * objects are pulled into the message.</P>
605 * @throws SOAPException if there
606 * was a problem saving changes to this message.
607 */
608 public void saveChanges() throws SOAPException {
609 if (mAttachments != null && 0 < mAttachments.getAttachmentCount()) {
610 try {
611 headers.setHeader("Content-Type",mAttachments.getContentType());
612 } catch (AxisFault af){
613 log.error(Messages.getMessage("exception00"), af);
614 }
615 }
616 saveRequired = false;
617 try {
618 /* Fix for Bug 16418 - Start from scratch */
619 mSOAPPart.saveChanges();
620 } catch (AxisFault axisFault) {
621 log.error(Messages.getMessage("exception00"), axisFault);
622 }
623 }
624
625 /**
626 * Indicates whether this <CODE>SOAPMessage</CODE> object
627 * has had the method <CODE>saveChanges</CODE> called on
628 * it.
629 * @return <CODE>true</CODE> if <CODE>saveChanges</CODE> has
630 * been called on this message at least once; <CODE>
631 * false</CODE> otherwise.
632 */
633 public boolean saveRequired() {
634 return saveRequired;
635 }
636
637 /**
638 * Returns all the transport-specific MIME headers for this
639 * <CODE>SOAPMessage</CODE> object in a transport-independent
640 * fashion.
641 * @return a <CODE>MimeHeaders</CODE> object containing the
642 * <CODE>MimeHeader</CODE> objects
643 */
644 public javax.xml.soap.MimeHeaders getMimeHeaders() {
645 return headers;
646 }
647
648 /**
649 * Removes all <CODE>AttachmentPart</CODE> objects that have
650 * been added to this <CODE>SOAPMessage</CODE> object.
651 *
652 * <P>This method does not touch the SOAP part.</P>
653 */
654 public void removeAllAttachments(){
655 mAttachments.removeAllAttachments();
656 }
657
658 /**
659 * Gets a count of the number of attachments in this
660 * message. This count does not include the SOAP part.
661 * @return the number of <CODE>AttachmentPart</CODE> objects
662 * that are part of this <CODE>SOAPMessage</CODE>
663 * object
664 */
665 public int countAttachments(){
666 return mAttachments == null ? 0 : mAttachments.getAttachmentCount();
667 }
668
669 /**
670 * Retrieves all the <CODE>AttachmentPart</CODE> objects
671 * that are part of this <CODE>SOAPMessage</CODE> object.
672 * @return an iterator over all the attachments in this
673 * message
674 */
675 public Iterator getAttachments(){
676 try {
677 if (mAttachments != null && 0 != mAttachments.getAttachmentCount()) {
678 return mAttachments.getAttachments().iterator();
679 }
680 } catch (AxisFault af){
681 log.error(Messages.getMessage("exception00"), af);
682 }
683 return Collections.EMPTY_LIST.iterator();
684 }
685
686 /**
687 * Retrieves all the <CODE>AttachmentPart</CODE> objects
688 * that have header entries that match the specified headers.
689 * Note that a returned attachment could have headers in
690 * addition to those specified.
691 * @param headers a <CODE>MimeHeaders</CODE>
692 * object containing the MIME headers for which to
693 * search
694 * @return an iterator over all attachments that have a header
695 * that matches one of the given headers
696 */
697 public Iterator getAttachments(javax.xml.soap.MimeHeaders headers){
698 return mAttachments.getAttachments(headers);
699 }
700
701 /**
702 * Adds the given <CODE>AttachmentPart</CODE> object to this
703 * <CODE>SOAPMessage</CODE> object. An <CODE>
704 * AttachmentPart</CODE> object must be created before it can be
705 * added to a message.
706 * @param attachmentpart an <CODE>
707 * AttachmentPart</CODE> object that is to become part of
708 * this <CODE>SOAPMessage</CODE> object
709 * @throws java.lang.IllegalArgumentException
710 */
711 public void addAttachmentPart(AttachmentPart attachmentpart){
712 try {
713 mAttachments.addAttachmentPart((org.apache.axis.Part)attachmentpart);
714 } catch (AxisFault af){
715 log.error(Messages.getMessage("exception00"), af);
716 }
717 }
718
719 /**
720 * Creates a new empty <CODE>AttachmentPart</CODE> object.
721 * Note that the method <CODE>addAttachmentPart</CODE> must be
722 * called with this new <CODE>AttachmentPart</CODE> object as
723 * the parameter in order for it to become an attachment to this
724 * <CODE>SOAPMessage</CODE> object.
725 * @return a new <CODE>AttachmentPart</CODE> object that can be
726 * populated and added to this <CODE>SOAPMessage</CODE>
727 * object
728 */
729 public AttachmentPart createAttachmentPart() {
730 if (!isAttachmentSupportEnabled(getMessageContext())) {
731 throw new RuntimeException(Messages.getMessage("noAttachments"));
732 }
733
734 try {
735 return (AttachmentPart) mAttachments.createAttachmentPart();
736 } catch (AxisFault af){
737 log.error(Messages.getMessage("exception00"), af);
738 }
739 return null;
740 }
741
742 /**
743 * Dispose of attachments.
744 */
745 public void dispose() {
746 if(mAttachments!=null) {
747 mAttachments.dispose();
748 }
749 }
750 }