/*
 * Copyright 2001-2004 The Apache Software Foundation.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.axis;

import org.apache.axis.attachments.Attachments;
import org.apache.axis.components.logger.LogFactory;
import org.apache.axis.message.SOAPEnvelope;
import org.apache.axis.message.MimeHeaders;
import org.apache.axis.soap.SOAPConstants;
import org.apache.axis.transport.http.HTTPConstants;
import org.apache.axis.utils.ClassUtils;
import org.apache.axis.utils.Messages;
import org.apache.axis.utils.XMLUtils;
import org.apache.commons.logging.Log;

import javax.xml.soap.AttachmentPart;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;

import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Iterator;
import java.util.Collections;

/**
 * A complete SOAP (and/or XML-RPC, eventually) message.
 * Includes both the root part (as a SOAPPart), and zero or
 * more MIME attachments (as AttachmentParts).
 * <p>
 * Eventually should be refactored to generalize SOAPPart
 * for multiple protocols (XML-RPC?).
 *
 * @author Rob Jellinghaus (robj@unrealities.com)
 * @author Doug Davis (dug@us.ibm.com)
 * @author Glen Daniels (gdaniels@allaire.com)
 * @author Rick Rineholt
 * @author Heejune Ahn (cityboy@tmax.co.kr)
 */
public class Message extends javax.xml.soap.SOAPMessage
    implements java.io.Serializable {

    /**
     * The <code>Log</code> that this class uses for logging all messages.
     */
    protected static Log log =
        LogFactory.getLog(Message.class.getName());

    /** Message is a request. */
    public static final String REQUEST = "request";

    /** Message is a a response. */
    public static final String RESPONSE = "response";

    /** MIME parts defined for messages. */
    public static final String MIME_MULTIPART_RELATED = "multipart/related";

    /** DIME parts defined for messages. */
    public static final String MIME_APPLICATION_DIME = "application/dime";

    /** Content Type for MTOM/XOP */
    public static final String CONTENT_TYPE_MTOM = "application/xop+xml";

    /** Default Attachments Implementation class. */
    public static final String DEFAULT_ATTACHMNET_IMPL="org.apache.axis.attachments.AttachmentsImpl";

    /** Current Attachment implementation. */
    private static String mAttachmentsImplClassName=DEFAULT_ATTACHMNET_IMPL;

    /** Look at the input stream to find the headers to decide the mime type. */
    public static final String MIME_UNKNOWN = "  ";

    // fixme: is this constrained to two values - request/response (e.g.
    //  REQUEST and RESPONSE)? If so, this needs documenting in the get/set
    //  methods and/or converting into a type-safe e-num. Potentially get/set
    //  methods should check these values & throw IllegalArgumentException
    /**
     * The messageType indicates whether this is request or response.
     */
    private String messageType;

    /**
     * This Message's SOAPPart.  Will always be here.
     */
    private SOAPPart mSOAPPart;

    /**
     * This Message's Attachments object, which manages the attachments
     * contained in this Message.
     */
    private Attachments mAttachments = null;

    private MimeHeaders headers;

    private boolean saveRequired = true;

    /**
     * Returns the name of the class prividing Attachment Implementation.
     *
     * @return class name
     */
    public static String getAttachmentImplClassName(){
        return mAttachmentsImplClassName;
    }

    private MessageContext msgContext;

    /**
     * Get the message type.
     *
     * @return the message type <code>String</code>
     */
    public String getMessageType() {
        return messageType;
    }

    /**
     *  Set the message type.
     *
     * @param messageType the message type <code>String</code>
     */
    public void setMessageType(String messageType) {
        this.messageType = messageType;
    }

    /**
     * Get the context associated with this message.
     *
     * @return  the message context for this message
     */
    public MessageContext getMessageContext() {
        return msgContext;
    }

    /**
     * Set the context associated with this message.
     *
     * @param msgContext  the message context for this message
     */
    public void setMessageContext(MessageContext msgContext) {
        this.msgContext = msgContext;
    }

    /**
     * Construct a Message, using the provided initialContents as the
     * contents of the Message's SOAPPart.
     * <p>
     * Eventually, genericize this to
     * return the RootPart instead, which will have some kind of
     * EnvelopeFactory to enable support for things other than SOAP.
     * But that all will come later, with lots of additional refactoring.
     *
     * @param initialContents may be String, byte[], InputStream, SOAPEnvelope,
     *                        or AxisFault.
     * @param bodyInStream is true if initialContents is an InputStream
     *                     containing just the SOAP body (no SOAP-ENV).
     */
    public Message(Object initialContents, boolean bodyInStream) {
        setup(initialContents, bodyInStream, null, null, null);
    }

    /**
     * Construct a Message, using the provided initialContents as the
     * contents of the Message's SOAPPart.
     * <p>
     * Eventually, genericize this to
     * return the RootPart instead, which will have some kind of
     * EnvelopeFactory to enable support for things other than SOAP.
     * But that all will come later, with lots of additional refactoring.
     *
     * @param initialContents may be String, byte[], InputStream, SOAPEnvelope,
     *                        or AxisFault.
     * @param bodyInStream is true if initialContents is an InputStream
     *                     containing just the SOAP body (no SOAP-ENV).
     * @param headers Mime Headers.
     */
    public Message(Object initialContents, boolean bodyInStream, javax.xml.soap.MimeHeaders headers) {
        setup(initialContents, bodyInStream, null, null, headers);
    }

    /**
     * Construct a Message, using the provided initialContents as the
     * contents of the Message's SOAPPart.
     * <p>
     * Eventually, genericize this to
     * return the RootPart instead, which will have some kind of
     * EnvelopeFactory to enable support for things other than SOAP.
     * But that all will come later, with lots of additional refactoring.
     *
     * @param initialContents may be String, byte[], InputStream, SOAPEnvelope,
     *                        or AxisFault.
     * @param headers Mime Headers.
     */
    public Message(Object initialContents, MimeHeaders headers) {
        setup(initialContents, true, null, null, headers);
    }

    /**
     * Construct a Message, using the provided initialContents as the
     * contents of the Message's SOAPPart.
     * <p>
     * Eventually, genericize this to
     * return the RootPart instead, which will have some kind of
     * EnvelopeFactory to enable support for things other than SOAP.
     * But that all will come later, with lots of additional refactoring.
     *
     * @param initialContents may be String, byte[], InputStream, SOAPEnvelope,
     *                        or AxisFault
     * @param bodyInStream is true if initialContents is an InputStream
     *                     containing just the SOAP body (no SOAP-ENV)
     * @param contentType this if the contentType has been already determined
     *                   (as in the case of servlets)
     * @param contentLocation the location of the content
     */
    public Message(Object initialContents,
                   boolean bodyInStream,
                   String contentType,
                   String contentLocation) {
        setup(initialContents, bodyInStream, contentType, contentLocation, null);
    }

    /**
     * Construct a Message.  An overload of Message(Object, boolean),
     * defaulting bodyInStream to false.
     *
     * @param initialContents may be String, byte[], InputStream, SOAPEnvelope,
     *                        or AxisFault
     */
    public Message(Object initialContents) {
        setup(initialContents, false, null, null, null);
    }

    private static Class attachImpl = null;

    //aviod testing and possibly failing everytime.
    private static boolean checkForAttachmentSupport = true;

    private static boolean attachmentSupportEnabled = false;

    private static synchronized boolean isAttachmentSupportEnabled(MessageContext mc) {
        if (checkForAttachmentSupport) {
            //aviod testing and possibly failing everytime.
            checkForAttachmentSupport = false;
            try {
                // Get the default setting from AxisProperties
                String attachImpName = AxisProperties.getProperty(AxisEngine.PROP_ATTACHMENT_IMPLEMENTATION,
                        AxisEngine.DEFAULT_ATTACHMENT_IMPL);
                // override the default with any changes specified in the engine configuration
                if (null != mc) {
                    AxisEngine ae = mc.getAxisEngine();
                    if (null != ae) {
                        attachImpName = (String) ae.getOption(
                                AxisEngine.PROP_ATTACHMENT_IMPLEMENTATION);
                    }
                }

                /**
                 * Attempt to resolve class name, verify that these are present...
                 */
                ClassUtils.forName("javax.activation.DataHandler");
                ClassUtils.forName("javax.mail.internet.MimeMultipart");

                attachImpl = ClassUtils.forName(attachImpName);

                attachmentSupportEnabled = true;
            } catch (ClassNotFoundException ex) {
                // no support for it, leave mAttachments null.
            } catch (java.lang.NoClassDefFoundError ex) {
                // no support for it, leave mAttachments null.
            } catch (java.lang.SecurityException ex) {
                // no support for it, leave mAttachments null.
            }
            log.debug(Messages.getMessage("attachEnabled") + "  " +
                    attachmentSupportEnabled);
        }
        return attachmentSupportEnabled;
    }

    /**
     * Do the work of construction.
     *
     * @param initialContents may be String, byte[], InputStream, SOAPEnvelope,
     *                        or AxisFault
     * @param bodyInStream is true if initialContents is an InputStream
     *                     containing just the SOAP body (no SOAP-ENV)
     * @param contentType this if the contentType has been already determined
     *                   (as in the case of servlets)
     * @param contentLocation the location of the content
     * @param mimeHeaders  mime headers for attachments
     */
    private void setup(Object initialContents, boolean bodyInStream,
                       String contentType, String contentLocation,
                       javax.xml.soap.MimeHeaders mimeHeaders) {

        if(contentType == null && mimeHeaders != null) {
            String contentTypes[] = mimeHeaders.getHeader("Content-Type");
            contentType = (contentTypes != null)? contentTypes[0] : null;
        }
        if(contentLocation == null && mimeHeaders != null) {
            String contentLocations[] = mimeHeaders.getHeader("Content-Location");
            contentLocation = (contentLocations != null)? contentLocations[0] : null;
        }
        if (contentType != null) {
            int delimiterIndex = contentType.lastIndexOf("charset");
            if (delimiterIndex > 0) {
                String charsetPart = contentType.substring(delimiterIndex);
                int delimiterIndex2 = charsetPart.indexOf(';');
                if(delimiterIndex2 != -1){
                    charsetPart = charsetPart.substring(0, delimiterIndex2);
                }
                int charsetIndex = charsetPart.indexOf('=');
                String charset = charsetPart.substring(charsetIndex + 1).trim();
                if ((charset.startsWith("\"") || charset.startsWith("\'"))) {
                    charset = charset.substring(1, charset.length());
                }
                if ((charset.endsWith("\"") || charset.endsWith("\'"))) {
                    charset = charset.substring(0, charset.length()-1);
                }
                try {
                    setProperty(SOAPMessage.CHARACTER_SET_ENCODING, charset);
                } catch (SOAPException e) {
                }
            }
        }
        // Try to construct an AttachmentsImpl object for attachment
        // functionality.
        // If there is no org.apache.axis.attachments.AttachmentsImpl class,
        // it must mean activation.jar is not present and attachments are not
        // supported.
        if (isAttachmentSupportEnabled(getMessageContext())) {
            // Construct one, and cast to Attachments.
            // There must be exactly one constructor of AttachmentsImpl, which
            // must take an org.apache.axis.Message!
            Constructor attachImplConstr = attachImpl.getConstructors()[0];
            try {
                mAttachments = (Attachments) attachImplConstr.newInstance(
                        new Object[] { initialContents,
                                       contentType, contentLocation});

                //If it can't support it, it wont have a root part.
                mSOAPPart = (SOAPPart) mAttachments.getRootPart();
            } catch (InvocationTargetException ex) {
                log.fatal(Messages.getMessage("invocationTargetException00"),
                          ex);
                throw new RuntimeException(ex.getMessage());
            } catch (InstantiationException ex) {
                log.fatal(Messages.getMessage("instantiationException00"),
                          ex);
                throw new RuntimeException(ex.getMessage());
            } catch (IllegalAccessException ex) {
                log.fatal(Messages.getMessage("illegalAccessException00"),
                          ex);
                throw new RuntimeException(ex.getMessage());
            }
        } else if (contentType != null && contentType.startsWith("multipart")){
            throw new RuntimeException(Messages.getMessage("noAttachments"));
        }

        // text/xml
        if (null == mSOAPPart) {
            mSOAPPart = new SOAPPart(this, initialContents, bodyInStream);
        }
        else
          mSOAPPart.setMessage(this);

        // The stream was not determined by a more complex type so default to
        if(mAttachments!=null) mAttachments.setRootPart(mSOAPPart);

        headers = (mimeHeaders == null) ? new MimeHeaders() : new MimeHeaders(mimeHeaders);
    }

    /**
     * Get this message's SOAPPart.
     * <p>
     * Eventually, this should be generalized beyond just SOAP,
     * but it's hard to know how to do that without necessitating
     * a lot of casts in client code.  Refactoring keeps getting
     * easier anyhow.
     *
     * @return the soap part of this message
     */
    public javax.xml.soap.SOAPPart getSOAPPart() {
        return mSOAPPart;
    }

    // fixme: do we realy need this? Can client code not just call
    //  getSOAPPart().getAsString() or is there some future optimization that
    //  could be hooked in here?
    /**
     * Get a string representation of this message's SOAPPart.
     *
     * @return the soap part of this message as a <code>String</code>
     * @throws org.apache.axis.AxisFault if the stringification failed
     */
    public String getSOAPPartAsString() throws org.apache.axis.AxisFault {
        return mSOAPPart.getAsString();
    }

    // fixme: do we realy need this? Can client code not just call
    //  getSOAPPart().getAsBytes() or is there some future optimization that
    //  could be hooked in here?
    /**
     * Get a byte array representation of this message's SOAPPart.
     *
     * @return the soap part of this message as a <code>byte[]</code>
     * @throws org.apache.axis.AxisFault if creating the byte[] failed
     */
    public byte[] getSOAPPartAsBytes() throws org.apache.axis.AxisFault {
        return mSOAPPart.getAsBytes();
    }

    /**
     * Get this message's SOAPPart as a SOAPEnvelope.
     *
     * @return a SOAPEnvelope containing this message's SOAPPart
     * @throws AxisFault if this failed
     */
    public SOAPEnvelope getSOAPEnvelope() throws AxisFault {
        return mSOAPPart.getAsSOAPEnvelope();
    }

    /**
     * Get the Attachments of this Message.
     * <p>
     * If this returns null, then NO ATTACHMENT SUPPORT EXISTS in this
     * configuration of Axis, and no attachment operations may be
     * performed.
     *
     * @return the <code>Attachments</code> if attachments are supported, null
     *              otherwise
     */
    public Attachments getAttachmentsImpl() {
        return mAttachments;
    }

    /**
     * Get the content type of the attachments.
     *
     * @param sc    provides the default content type
     * @return      a <code>String</code> giving the content type of the
     *              attachment
     * @throws AxisFault if there was an error deducing the content type from
     *              this message
     */
    public String getContentType(SOAPConstants sc) throws AxisFault {
        boolean soap12 = false;
        
        if(sc != null) {
            if(sc == SOAPConstants.SOAP12_CONSTANTS) {
                soap12 = true;
            }
        } else {
            // Support of SOAP 1.2 HTTP binding
            SOAPEnvelope envelope = getSOAPEnvelope();
            if (envelope != null) {
                if (envelope.getSOAPConstants() == SOAPConstants.SOAP12_CONSTANTS) {
                    soap12 = true;
                }
            }
        }

        String encoding = XMLUtils.getEncoding(this, msgContext);;
        String ret = sc.getContentType() + "; charset=" + encoding.toLowerCase();
        
        // Support of SOAP 1.2 HTTP binding
        if (soap12) {
            ret = HTTPConstants.HEADER_ACCEPT_APPL_SOAP +"; charset=" + encoding;
        }

        if (getSendType() != Attachments.SEND_TYPE_NONE && mAttachments != null &&
                0 != mAttachments.getAttachmentCount()) {
            ret = mAttachments.getContentType();
        }
        return ret;
    }

    private int getSendType() {
        int sendType = Attachments.SEND_TYPE_NOTSET;
        if ((msgContext != null) && (msgContext.getService() != null)) {
            sendType = msgContext.getService().getSendType();
        }
        return sendType;
    }

    //This will have to give way someday to HTTP Chunking but for now kludge.
    /**
     * Get the content length, including both soap and any attachments.
     *
     * @return the total length of this message in bytes
     * @throws org.apache.axis.AxisFault if there was a problem that prevented
     *              the length being calculated
     */
    public long getContentLength() throws org.apache.axis.AxisFault {
        long ret = mSOAPPart.getContentLength();
        if (mAttachments != null && 0 < mAttachments.getAttachmentCount()) {
            ret = mAttachments.getContentLength();
        }
        return ret;
    }

    /**
     * Writes this <CODE>SOAPMessage</CODE> object to the given
     *   output stream. The externalization format is as defined by
     *   the SOAP 1.1 with Attachments specification.
     *
     *   <P>If there are no attachments, just an XML stream is
     *   written out. For those messages that have attachments,
     *   <CODE>writeTo</CODE> writes a MIME-encoded byte stream.</P>
     * @param os the <CODE>OutputStream</CODE>
     *     object to which this <CODE>SOAPMessage</CODE> object will
     *     be written
     * @throws SOAPException  if there was a problem in
     *     externalizing this SOAP message
     * @throws IOException  if an I/O error
     *     occurs
     */
    public void writeTo(java.io.OutputStream os) throws SOAPException, IOException {
         //Do it the old fashion way.
        if (getSendType() == Attachments.SEND_TYPE_NONE || mAttachments == null || 0 == mAttachments.getAttachmentCount()) {
            try {
                String charEncoding = XMLUtils.getEncoding(this, msgContext);;
                mSOAPPart.setEncoding(charEncoding);
                mSOAPPart.writeTo(os);
            } catch (java.io.IOException e) {
                log.error(Messages.getMessage("javaIOException00"), e);
            }
        } else {
            try {
                mAttachments.writeContentToStream(os);
            } catch (java.lang.Exception e) {
                log.error(Messages.getMessage("exception00"), e);
            }
        }
    }

    private java.util.Hashtable mProps = new java.util.Hashtable();
    
    public SOAPBody getSOAPBody() throws SOAPException {
        return mSOAPPart.getEnvelope().getBody();
    }

    public SOAPHeader getSOAPHeader() throws SOAPException {
        return mSOAPPart.getEnvelope().getHeader();
    }

    public void setProperty(String property, Object value) throws SOAPException {
        mProps.put(property, value);
    }

    public Object getProperty(String property) throws SOAPException {
        return mProps.get(property);
    }

    /**
     * Retrieves a description of this <CODE>SOAPMessage</CODE>
     * object's content.
     * @return  a <CODE>String</CODE> describing the content of this
     *     message or <CODE>null</CODE> if no description has been
     *     set
     * @see #setContentDescription(java.lang.String) setContentDescription(java.lang.String)
     */
    public String getContentDescription() {
        String values[] = headers.getHeader(HTTPConstants.HEADER_CONTENT_DESCRIPTION);
        if(values != null && values.length > 0)
            return values[0];
        return null;
    }

    /**
     * Sets the description of this <CODE>SOAPMessage</CODE>
     * object's content with the given description.
     * @param  description a <CODE>String</CODE>
     *     describing the content of this message
     * @see #getContentDescription() getContentDescription()
     */
    public void setContentDescription(String description) {
        headers.setHeader(HTTPConstants.HEADER_CONTENT_DESCRIPTION, description);
    }

    /**
     * Updates this <CODE>SOAPMessage</CODE> object with all the
     *   changes that have been made to it. This method is called
     *   automatically when a message is sent or written to by the
     *   methods <CODE>ProviderConnection.send</CODE>, <CODE>
     *   SOAPConnection.call</CODE>, or <CODE>
     *   SOAPMessage.writeTo</CODE>. However, if changes are made to
     *   a message that was received or to one that has already been
     *   sent, the method <CODE>saveChanges</CODE> needs to be
     *   called explicitly in order to save the changes. The method
     *   <CODE>saveChanges</CODE> also generates any changes that
     *   can be read back (for example, a MessageId in profiles that
     *   support a message id). All MIME headers in a message that
     *   is created for sending purposes are guaranteed to have
     *   valid values only after <CODE>saveChanges</CODE> has been
     *   called.
     *
     *   <P>In addition, this method marks the point at which the
     *   data from all constituent <CODE>AttachmentPart</CODE>
     *   objects are pulled into the message.</P>
     * @throws  SOAPException if there
     *     was a problem saving changes to this message.
     */
    public void saveChanges() throws SOAPException {
        headers.removeHeader("Content-Length");
        if (mAttachments != null && 0 < mAttachments.getAttachmentCount()) {
            try {
                headers.setHeader("Content-Type",mAttachments.getContentType());
            } catch (AxisFault af){
                log.error(Messages.getMessage("exception00"), af);
            }
        }
        saveRequired = false;
        try {
            /* Fix for Bug 16418 - Start from scratch */ 
            mSOAPPart.saveChanges();
        } catch (AxisFault axisFault) {
            log.error(Messages.getMessage("exception00"), axisFault);
        }
    }

    /**
     * Indicates whether this <CODE>SOAPMessage</CODE> object
     * has had the method <CODE>saveChanges</CODE> called on
     * it.
     * @return <CODE>true</CODE> if <CODE>saveChanges</CODE> has
     *     been called on this message at least once; <CODE>
     *     false</CODE> otherwise.
     */
    public boolean saveRequired() {
        return saveRequired;
    }

    /**
     * Returns all the transport-specific MIME headers for this
     * <CODE>SOAPMessage</CODE> object in a transport-independent
     * fashion.
     * @return a <CODE>MimeHeaders</CODE> object containing the
     *     <CODE>MimeHeader</CODE> objects
     */
    public javax.xml.soap.MimeHeaders getMimeHeaders() {
        return headers;
    }

    /**
     * Removes all <CODE>AttachmentPart</CODE> objects that have
     *   been added to this <CODE>SOAPMessage</CODE> object.
     *
     *   <P>This method does not touch the SOAP part.</P>
     */
    public void removeAllAttachments(){
        mAttachments.removeAllAttachments();
    }

    /**
     * Gets a count of the number of attachments in this
     * message. This count does not include the SOAP part.
     * @return  the number of <CODE>AttachmentPart</CODE> objects
     *     that are part of this <CODE>SOAPMessage</CODE>
     *     object
     */
    public int countAttachments(){
        return mAttachments == null ? 0 : mAttachments.getAttachmentCount();
    }

    /**
     * Retrieves all the <CODE>AttachmentPart</CODE> objects
     * that are part of this <CODE>SOAPMessage</CODE> object.
     * @return  an iterator over all the attachments in this
     *     message
     */
    public Iterator getAttachments(){
        try {
            if (mAttachments != null && 0 != mAttachments.getAttachmentCount()) {
                return mAttachments.getAttachments().iterator();
            }
        } catch (AxisFault af){
            log.error(Messages.getMessage("exception00"), af);
        }
        return Collections.EMPTY_LIST.iterator();
    }

    /**
     * Retrieves all the <CODE>AttachmentPart</CODE> objects
     * that have header entries that match the specified headers.
     * Note that a returned attachment could have headers in
     * addition to those specified.
     * @param   headers a <CODE>MimeHeaders</CODE>
     *     object containing the MIME headers for which to
     *     search
     * @return an iterator over all attachments that have a header
     *     that matches one of the given headers
     */
    public Iterator getAttachments(javax.xml.soap.MimeHeaders headers){
        return mAttachments.getAttachments(headers);
    }

    /**
     * Adds the given <CODE>AttachmentPart</CODE> object to this
     * <CODE>SOAPMessage</CODE> object. An <CODE>
     * AttachmentPart</CODE> object must be created before it can be
     * added to a message.
     * @param  attachmentpart an <CODE>
     *     AttachmentPart</CODE> object that is to become part of
     *     this <CODE>SOAPMessage</CODE> object
     * @throws java.lang.IllegalArgumentException
     */
    public void addAttachmentPart(AttachmentPart attachmentpart){
        try {
            mAttachments.addAttachmentPart((org.apache.axis.Part)attachmentpart);
        } catch (AxisFault af){
            log.error(Messages.getMessage("exception00"), af);
        }
    }

    /**
     * Creates a new empty <CODE>AttachmentPart</CODE> object.
     * Note that the method <CODE>addAttachmentPart</CODE> must be
     * called with this new <CODE>AttachmentPart</CODE> object as
     * the parameter in order for it to become an attachment to this
     * <CODE>SOAPMessage</CODE> object.
     * @return  a new <CODE>AttachmentPart</CODE> object that can be
     *     populated and added to this <CODE>SOAPMessage</CODE>
     *     object
     */
    public AttachmentPart createAttachmentPart() {
        if (!isAttachmentSupportEnabled(getMessageContext())) {
            throw new RuntimeException(Messages.getMessage("noAttachments"));
        }
        
        try {
            return (AttachmentPart) mAttachments.createAttachmentPart();
        } catch (AxisFault af){
            log.error(Messages.getMessage("exception00"), af);
        }
        return null;
    }

    /**
     * Dispose of attachments.
     */
    public void dispose() {
        if(mAttachments!=null) {
            mAttachments.dispose();
        }
    }
}
