Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

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 }