/*
 * 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.components.logger.LogFactory;
import org.apache.axis.encoding.DeserializationContext;
import org.apache.axis.encoding.SerializationContext;
import org.apache.axis.message.InputStreamBody;
import org.apache.axis.message.MimeHeaders;
import org.apache.axis.message.SOAPDocumentImpl;
import org.apache.axis.message.SOAPEnvelope;
import org.apache.axis.message.SOAPHeaderElement;
import org.apache.axis.transport.http.HTTPConstants;
import org.apache.axis.utils.ByteArray;
import org.apache.axis.utils.Messages;
import org.apache.axis.utils.SessionUtils;
import org.apache.axis.utils.XMLUtils;
import org.apache.axis.handlers.HandlerChainImpl;
import org.apache.commons.logging.Log;
import org.w3c.dom.Attr;
import org.w3c.dom.CDATASection;
import org.w3c.dom.Comment;
import org.w3c.dom.DOMException;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentFragment;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Element;
import org.w3c.dom.EntityReference;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.ProcessingInstruction;
import org.w3c.dom.Text;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamSource;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.util.Iterator;
import java.util.Vector;

/**
 * The SOAPPart provides access to the root part of the Message which
 * contains the envelope.
 * <p>
 * SOAPPart implements Part, providing common MIME operations.
 * <p>
 * SOAPPart also allows access to its envelope,
 * as a string, byte[], InputStream, or SOAPEnvelope.  (This functionality
 * used to be in Message, and has been moved here more or less verbatim
 * pending further cleanup.)
 *
 * @author Rob Jellinghaus (robj@unrealities.com)
 * @author Doug Davis (dug@us.ibm.com)
 * @author Glen Daniels (gdaniels@allaire.com)
 * @author Heejune Ahn (cityboy@tmax.co.kr)
 */
public class SOAPPart extends javax.xml.soap.SOAPPart implements Part
{
    protected static Log log =
        LogFactory.getLog(SOAPPart.class.getName());

    public static final int FORM_STRING       = 1;
    public static final int FORM_INPUTSTREAM  = 2;
    public static final int FORM_SOAPENVELOPE = 3;
    public static final int FORM_BYTES        = 4;
    public static final int FORM_BODYINSTREAM = 5;
    public static final int FORM_FAULT        = 6;
    public static final int FORM_OPTIMIZED    = 7;
    private int currentForm;

    /**
     * property used to set SOAPEnvelope as default form
     */
    public static final String ALLOW_FORM_OPTIMIZATION = "axis.form.optimization";

    
    //private Hashtable headers = new Hashtable();
    private MimeHeaders mimeHeaders = new MimeHeaders();

    private static final String[] formNames =
    { "", "FORM_STRING", "FORM_INPUTSTREAM", "FORM_SOAPENVELOPE",
      "FORM_BYTES", "FORM_BODYINSTREAM", "FORM_FAULT", "FORM_OPTIMIZED" };

    /**
     * The current representation of the SOAP contents of this part.
     * May be a String, byte[], InputStream, or SOAPEnvelope, depending
     * on whatever was last asked for.  (ack)
     * <p>
     * currentForm must have the corresponding value.
     * <p>
     * As someone once said:  "Just a placeholder until we figure out what the actual Message
     * object is."
     */
    private Object currentMessage ;

    /**
     * default message encoding charset
     */
    private String currentEncoding = "UTF-8";

    // These two fields are used for caching in getAsString and getAsBytes
    private String currentMessageAsString = null;
    private byte[] currentMessageAsBytes = null;
    private org.apache.axis.message.SOAPEnvelope currentMessageAsEnvelope= null;

    /**
     * Message object this part is tied to. Used for serialization settings.
     */
    private Message msgObject;

    /** Field contentSource. */
    private Source contentSource = null;

    /**
     * The original message.  Again, may be String, byte[], InputStream,
     * or SOAPEnvelope.
     */
    // private Object originalMessage ; //free up reference  this is not in use.

    /**
     * Create a new SOAPPart.
     * <p>
     * Do not call this directly!  Should only be called by Message.
     *
     * @param parent  the parent <code>Message</code>
     * @param initialContents  the initial contens <code>Object</code>
     * @param isBodyStream if the body is in a stream
     */
    public SOAPPart(Message parent, Object initialContents, boolean isBodyStream) {

        setMimeHeader(HTTPConstants.HEADER_CONTENT_ID , SessionUtils.generateSessionId());
        setMimeHeader(HTTPConstants.HEADER_CONTENT_TYPE , "text/xml");

        msgObject=parent;
        // originalMessage = initialContents;
        int form = FORM_STRING;
        if (initialContents instanceof SOAPEnvelope) {
            form = FORM_SOAPENVELOPE;
            ((SOAPEnvelope)initialContents).setOwnerDocument(this);
        } else if (initialContents instanceof InputStream) {
            form = isBodyStream ? FORM_BODYINSTREAM : FORM_INPUTSTREAM;
        } else if (initialContents instanceof byte[]) {
            form = FORM_BYTES;
        } else if (initialContents instanceof AxisFault) {
            form = FORM_FAULT;
        }

        if (log.isDebugEnabled()) {
            log.debug("Enter: SOAPPart ctor(" + formNames[form] + ")");
        }

        setCurrentMessage(initialContents, form);

        if (log.isDebugEnabled()) {
            log.debug("Exit: SOAPPart ctor()");
        }
    }


    /**
     * Get the <code>Message</code> for this <code>Part</code>.
     *
     * @return the <code>Message</code> for this <code>Part</code>
     */
    public Message getMessage(){
      return msgObject;
    }

    /**
     * Set the Message for this Part.
     * Do not call this Directly. Called by Message.
     *
     * @param msg  the <code>Message</code> for this part
     */
    public void setMessage (Message msg) {
        this.msgObject= msg;
    }

    /**
     * Content type is always "text/xml" for SOAPParts.
     *
     * @return the content type
     */
    public String getContentType() {
        return "text/xml";
    }

    /**
     * Get the content length for this SOAPPart.
     * This will force buffering of the SOAPPart, but it will
     * also cache the byte[] form of the SOAPPart.
     *
     * @return the content length in bytes
     */
    public long getContentLength() throws AxisFault {
        saveChanges();
        if (currentForm == FORM_OPTIMIZED) {
            return ((ByteArray) currentMessage).size();
        } else if (currentForm == FORM_BYTES) {
            return ((byte[]) currentMessage).length;
        }
        byte[] bytes = this.getAsBytes();
        return bytes.length;
    }

    /**
     * This set the SOAP Envelope for this part.
     * <p>
     * Note: It breaks the chicken/egg created.
     *  I need a message to create an attachment...
     *  From the attachment I should be able to get a reference...
     *  I now want to edit elements in the envelope in order to
     *    place the  attachment reference to it.
     *  How do I now update the SOAP envelope with what I've changed?
     *
     * @param env   the <code>SOAPEnvelope</CODE> for this <code>SOAPPart</code>
     */

    public void setSOAPEnvelope(org.apache.axis.message.SOAPEnvelope env){
       setCurrentMessage(env, FORM_SOAPENVELOPE) ;
    }

    /**
     * Write the contents to the specified stream.
     *
     * @param os  the <code>java.io.OutputStream</code> to write to
     */
    public void writeTo(java.io.OutputStream os) throws IOException {
        if ( currentForm == FORM_BYTES ) {
            os.write((byte[])currentMessage);
        } else if ( currentForm == FORM_OPTIMIZED ) {
            ((ByteArray) currentMessage).writeTo(os);
        } else {
            Writer writer = new OutputStreamWriter(os, currentEncoding);
            writer = new BufferedWriter(new PrintWriter(writer));
            writeTo(writer);
            writer.flush();
        }
    }

    /**
     * Write the contents to the specified writer.
     *
     * @param writer  the <code>Writer</code> to write to
     */
    public void writeTo(Writer writer) throws IOException {
        boolean inclXmlDecl = false;         
        
        if (msgObject.getMessageContext() != null) {    // if we have message context (JAX-RPC), write xml decl always. 
            inclXmlDecl = true;            
        } else {    // if we have no message context (SAAJ), write xml decl according to property.
            try {
                String xmlDecl = (String)msgObject.getProperty(SOAPMessage.WRITE_XML_DECLARATION);
                if (xmlDecl != null && xmlDecl.equals("true")) {
                    inclXmlDecl = true;                    
                }                
            } catch (SOAPException e) {
                throw new IOException(e.getMessage());
            }
        }
        
        if ( currentForm == FORM_FAULT ) {
            AxisFault env = (AxisFault)currentMessage;
            try {
                SerializationContext serContext = new SerializationContext(writer, getMessage().getMessageContext()); 
                serContext.setSendDecl(inclXmlDecl);
                serContext.setEncoding(currentEncoding);
                env.output(serContext);
            } catch (Exception e) {
                log.error(Messages.getMessage("exception00"), e);
                throw env;
            }
            return;
        }

        if ( currentForm == FORM_SOAPENVELOPE ) {
            SOAPEnvelope env = (SOAPEnvelope)currentMessage;
            try {
                SerializationContext serContext = new SerializationContext(writer, getMessage().getMessageContext());
                serContext.setSendDecl(inclXmlDecl);
                serContext.setEncoding(currentEncoding);
                env.output(serContext);
            } catch (Exception e) {
                throw AxisFault.makeFault(e);
            }
            return;
        }

        String xml = this.getAsString();
        if(inclXmlDecl){
            if(!xml.startsWith("<?xml")){
                writer.write("<?xml version=\"1.0\" encoding=\"");
                writer.write(currentEncoding);
                writer.write("\"?>");
            }
        }
        writer.write(xml);
    }

    /**
     * Get the current message, in whatever form it happens to be right now.
     * Will return a String, byte[], InputStream, or SOAPEnvelope, depending
     * on circumstances.
     * <p>
     * The method name is historical.
     * TODO: rename this for clarity; should be more like getContents.
     *
     * @return the current content
     */
    public Object getCurrentMessage() {
        return currentMessage;
    }

    /**
     * Set the current message
     * @param currMsg
     * @param form
     */
    public void setCurrentMessage(Object currMsg, int form) {
      currentMessageAsString = null; //Get rid of any cached stuff this is new.
      currentMessageAsBytes = null;
      currentMessageAsEnvelope= null;
      setCurrentForm(currMsg, form);
    }
    /**
     * Set the current contents of this Part.
     * The method name is historical.
     * TODO: rename this for clarity to something more like setContents???
     *
     * @param currMsg  the new content of this part
     * @param form  the form of the message
     */
    private void setCurrentForm(Object currMsg, int form) {
        if (log.isDebugEnabled()) {
            String msgStr;
            if (currMsg instanceof String) {
                msgStr = (String)currMsg;
            } else {
                msgStr = currMsg.getClass().getName();
            }
            log.debug(Messages.getMessage("setMsgForm", formNames[form],
                    "" + msgStr));
        }

        // only change form if allowed
        if (isFormOptimizationAllowed()) {
            currentMessage = currMsg;
            currentForm = form;
            if (currentForm == FORM_SOAPENVELOPE) {
                    currentMessageAsEnvelope = (org.apache.axis.message.SOAPEnvelope) currMsg;
            }
        }
    }

    /**
     * check if the allow optimization flag is on
     * @return form optimization flag
     */ 
    private boolean isFormOptimizationAllowed() {
        boolean allowFormOptimization = true;
        Message msg = getMessage();
        if (msg != null) {
            MessageContext ctx = msg.getMessageContext();
            if (ctx != null) {
                Boolean propFormOptimization = (Boolean)ctx.getProperty(ALLOW_FORM_OPTIMIZATION);
                if (propFormOptimization != null) {
                    allowFormOptimization = propFormOptimization.booleanValue();
                }
            }
        }
        return allowFormOptimization;
    }

    public int getCurrentForm() {
        return currentForm;
    }
    
    /**
     * Get the contents of this Part (not the headers!), as a byte
     * array.  This will force buffering of the message.
     *
     * @return an array of bytes containing a byte representation of this Part
     * @throws AxisFault if this Part can't be serialized to the byte array
     */
    public byte[] getAsBytes() throws AxisFault {
        log.debug("Enter: SOAPPart::getAsBytes");
        if ( currentForm == FORM_OPTIMIZED ) {
            log.debug("Exit: SOAPPart::getAsBytes");
            try {
                return ((ByteArray) currentMessage).toByteArray();
            } catch (IOException e) {
                throw AxisFault.makeFault(e);
            }
        }
        if ( currentForm == FORM_BYTES ) {
            log.debug("Exit: SOAPPart::getAsBytes");
            return (byte[])currentMessage;
        }

        if ( currentForm == FORM_BODYINSTREAM ) {
            try {
                getAsSOAPEnvelope();
            } catch (Exception e) {
                log.fatal(Messages.getMessage("makeEnvFail00"), e);
                log.debug("Exit: SOAPPart::getAsBytes");
                return null;
            }
        }

        if ( currentForm == FORM_INPUTSTREAM ) {
            // Assumes we don't need a content length
            try {
                InputStream  inp = null;
                byte[]  buf = null;
                try{
                    inp = (InputStream) currentMessage ;
                    ByteArrayOutputStream  baos = new ByteArrayOutputStream();
                    buf = new byte[4096];
                    int len ;
                    while ( (len = inp.read(buf,0,4096)) != -1 )
                        baos.write( buf, 0, len );
                    buf = baos.toByteArray();
                }finally{
                  if(inp != null &&
                    currentMessage instanceof org.apache.axis.transport.http.SocketInputStream )
                    inp.close();
                }
                setCurrentForm( buf, FORM_BYTES );
                log.debug("Exit: SOAPPart::getAsBytes");
                return (byte[])currentMessage;
            }
            catch( Exception e ) {
                log.error(Messages.getMessage("exception00"), e);
            }
            log.debug("Exit: SOAPPart::getAsBytes");
            return null;
        }

        if ( currentForm == FORM_SOAPENVELOPE ||
             currentForm == FORM_FAULT ){
            currentEncoding = XMLUtils.getEncoding(msgObject, null);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            BufferedOutputStream os = new BufferedOutputStream(baos);
            try {
                this.writeTo(os);
                os.flush();
            } catch (Exception e) {
                throw AxisFault.makeFault(e);
            }
            setCurrentForm(baos.toByteArray(), FORM_BYTES);
            if (log.isDebugEnabled()) {
                log.debug("Exit: SOAPPart::getAsBytes(): " + currentMessage);
            }
            return (byte[]) currentMessage;
        }

        if ( currentForm == FORM_STRING ) {
            // If the current message was already converted from
            // a byte[] to String, return the byte[] representation
            // (this is done to avoid unnecessary conversions)
            if (currentMessage == currentMessageAsString &&
                currentMessageAsBytes != null) {
                if (log.isDebugEnabled()) {
                    log.debug("Exit: SOAPPart::getAsBytes()");
                }
                return currentMessageAsBytes;
            }
            // Save this message in case it is requested later in getAsString
            currentMessageAsString = (String) currentMessage;
            try{
                currentEncoding = XMLUtils.getEncoding(msgObject, null);
                setCurrentForm( ((String)currentMessage).getBytes(currentEncoding),
                    FORM_BYTES );
            }catch(UnsupportedEncodingException ue){
               setCurrentForm( ((String)currentMessage).getBytes(),
                               FORM_BYTES );
            }
            currentMessageAsBytes = (byte[]) currentMessage;

            log.debug("Exit: SOAPPart::getAsBytes");
            return (byte[])currentMessage;
        }

        log.error(Messages.getMessage("cantConvert00", ""+currentForm));

        log.debug("Exit: SOAPPart::getAsBytes");
        return null;
    }

    public void saveChanges() throws AxisFault {
        log.debug("Enter: SOAPPart::saveChanges");
        if ( currentForm == FORM_SOAPENVELOPE ||
             currentForm == FORM_FAULT ){
            currentEncoding = XMLUtils.getEncoding(msgObject, null);
            ByteArray array = new ByteArray();
            try {
            	writeTo(array);
                array.flush();
            } catch (Exception e) {
                throw AxisFault.makeFault(e);
            }
            setCurrentForm( array, FORM_OPTIMIZED );
            if (log.isDebugEnabled()) {
                log.debug("Exit: SOAPPart::saveChanges(): " + currentMessage);
            }
        }
    }
    /**
     * Get the contents of this Part (not the headers!), as a String.
     * This will force buffering of the message.
     *
     * @return a <code>String</code> containing the content of this message
     * @throws AxisFault  if there is an error serializing this part
     */
    public String getAsString() throws AxisFault {
        log.debug("Enter: SOAPPart::getAsString");
        if ( currentForm == FORM_STRING ) {
            if (log.isDebugEnabled()) {
                log.debug("Exit: SOAPPart::getAsString(): " + currentMessage);
            }
            return (String)currentMessage;
        }

        if ( currentForm == FORM_INPUTSTREAM ||
             currentForm == FORM_BODYINSTREAM ) {
            getAsBytes();
            // Fall thru to "Bytes"
        }

        if ( currentForm == FORM_OPTIMIZED) {
            try {
                currentMessageAsBytes =
                        ((ByteArray) currentMessage).toByteArray();
            } catch (IOException e) {
                throw AxisFault.makeFault(e);
            }

            try{
                setCurrentForm(new String((byte[])currentMessageAsBytes,
                                currentEncoding),
                        FORM_STRING);
            }catch(UnsupportedEncodingException ue){
                setCurrentForm( new String((byte[]) currentMessageAsBytes),
                                   FORM_STRING );
            }
            if (log.isDebugEnabled()) {
                log.debug("Exit: SOAPPart::getAsString(): " + currentMessage);
            }
            return (String)currentMessage;
        }

        if ( currentForm == FORM_BYTES ) {
            // If the current message was already converted from
            // a String to byte[], return the String representation
            // (this is done to avoid unnecessary conversions)
            if (currentMessage == currentMessageAsBytes &&
                currentMessageAsString != null) {
                if (log.isDebugEnabled()) {
                    log.debug("Exit: SOAPPart::getAsString(): " + currentMessageAsString);
                }
                return currentMessageAsString;
            }
            
            // Save this message in case it is requested later in getAsBytes
            currentMessageAsBytes = (byte[]) currentMessage;
            try{
                setCurrentForm(new String((byte[])currentMessage,
                                currentEncoding),
                        FORM_STRING);
            }catch(UnsupportedEncodingException ue){
                setCurrentForm( new String((byte[]) currentMessage),
                                   FORM_STRING );
            }
            currentMessageAsString = (String) currentMessage;
            if (log.isDebugEnabled()) {
                log.debug("Exit: SOAPPart::getAsString(): " + currentMessage);
            }
            return (String)currentMessage;
        }

        if ( currentForm == FORM_FAULT ) {
            StringWriter writer = new StringWriter();
            try {
                this.writeTo(writer);
            } catch (Exception e) {
                log.error(Messages.getMessage("exception00"), e);
                return null;
            }
            setCurrentForm(writer.getBuffer().toString(), FORM_STRING);
            if (log.isDebugEnabled()) {
                log.debug("Exit: SOAPPart::getAsString(): " + currentMessage);
            }
            return (String)currentMessage;
        }

        if ( currentForm == FORM_SOAPENVELOPE ) {
            StringWriter writer = new StringWriter();
            try {
                this.writeTo(writer);
            } catch (Exception e) {
                throw AxisFault.makeFault(e);
            }
            setCurrentForm(writer.getBuffer().toString(), FORM_STRING);
            if (log.isDebugEnabled()) {
                log.debug("Exit: SOAPPart::getAsString(): " + currentMessage);
            }
            return (String)currentMessage;
        }

        log.error( Messages.getMessage("cantConvert01", ""+currentForm));

        log.debug("Exit: SOAPPart::getAsString()");
        return null;
    }

    /**
     * Get the contents of this Part (not the MIME headers!), as a
     * SOAPEnvelope.  This will force a complete parse of the
     * message.
     *
     * @return a <code>SOAPEnvelope</code> containing the message content
     * @throws AxisFault if the envelope could not be constructed
     */
    public SOAPEnvelope getAsSOAPEnvelope()
        throws AxisFault
    {
        if (log.isDebugEnabled()) {
            log.debug("Enter: SOAPPart::getAsSOAPEnvelope()");
            log.debug(Messages.getMessage("currForm", formNames[currentForm]));
        }
        if ( currentForm == FORM_SOAPENVELOPE )
            return (SOAPEnvelope)currentMessage;


        if (currentForm == FORM_BODYINSTREAM) {
            InputStreamBody bodyEl =
                             new InputStreamBody((InputStream)currentMessage);
            SOAPEnvelope env = new SOAPEnvelope();
            env.setOwnerDocument(this);
            env.addBodyElement(bodyEl);
            setCurrentForm(env, FORM_SOAPENVELOPE);
            return env;
        }

        InputSource is;

        if ( currentForm == FORM_INPUTSTREAM ) {
            is = new InputSource( (InputStream) currentMessage );
            String encoding = XMLUtils.getEncoding(msgObject, null, null);
            if (encoding != null) {
                currentEncoding = encoding;
                is.setEncoding(currentEncoding);
            }
        } else {
            is = new InputSource(new StringReader(getAsString()));
        }
        DeserializationContext dser = new DeserializationContext(is,
                                           getMessage().getMessageContext(),
                                           getMessage().getMessageType());
        dser.getEnvelope().setOwnerDocument(this);
        // This may throw a SAXException
        try {
            dser.parse();
        } catch (SAXException e) {
            Exception real = e.getException();
            if (real == null)
                real = e;
            throw AxisFault.makeFault(real);
        }

        SOAPEnvelope nse= dser.getEnvelope();
        if(currentMessageAsEnvelope != null){
          //Need to synchronize back processed header info.
          Vector newHeaders= nse.getHeaders();
          Vector oldHeaders= currentMessageAsEnvelope.getHeaders();
          if( null != newHeaders && null != oldHeaders){
           Iterator ohi= oldHeaders.iterator();
           Iterator nhi= newHeaders.iterator();
           while( ohi.hasNext() && nhi.hasNext()){
             SOAPHeaderElement nhe= (SOAPHeaderElement)nhi.next();
             SOAPHeaderElement ohe= (SOAPHeaderElement)ohi.next();

             if(ohe.isProcessed()) nhe.setProcessed(true);
           }
          }

        }

        setCurrentForm(nse, FORM_SOAPENVELOPE);

        log.debug("Exit: SOAPPart::getAsSOAPEnvelope");
        SOAPEnvelope env = (SOAPEnvelope)currentMessage;
        env.setOwnerDocument(this);
        return env;
    }

    /**
     * Add the specified MIME header, as per JAXM.
     *
     * @param header  the header to add
     * @param value   the value of that header
     */
    public void addMimeHeader (String header, String value) {
        mimeHeaders.addHeader(header, value);
    }

    /**
     * Get the specified MIME header.
     *
     * @param header  the name of a MIME header
     * @return the value of the first header named <code>header</code>
     */
    private String getFirstMimeHeader (String header) {
        String[] values = mimeHeaders.getHeader(header);
        if(values != null && values.length>0)
            return values[0];
        return null;
    }

    /**
     * Total size in bytes (of all content and headers, as encoded).
    public abstract int getSize();
     */

    /**
     * Content location.
     *
     * @return the content location
     */
    public String getContentLocation() {
        return getFirstMimeHeader(HTTPConstants.HEADER_CONTENT_LOCATION);
    }

    /**
     * Set content location.
     *
     * @param loc  the content location
     */
    public void setContentLocation(String loc) {
        setMimeHeader(HTTPConstants.HEADER_CONTENT_LOCATION, loc);
    }

    /**
     * Sets Content-Id of this part.
     *  already defined.
     * @param newCid new Content-Id
     */
    public void setContentId(String newCid){
        setMimeHeader(HTTPConstants.HEADER_CONTENT_ID,newCid);
    }

    /**
     * Content ID.
     *
     * @return the content ID
     */
    public String getContentId() {
        return getFirstMimeHeader(HTTPConstants.HEADER_CONTENT_ID);
    }
    /**
     * Content ID.
     *
     * @return the contentId reference value that should be used directly
     * as an href in a SOAP element to reference this attachment.
     * <B>Not part of JAX-RPC, JAX-M, SAAJ, etc. </B>
     */
    public String getContentIdRef() {
      return org.apache.axis.attachments.Attachments.CIDprefix +
         getContentId();
    }


    /**
     * Get all headers that match.
     *
     * @param match  an array of <code>String</code>s giving mime header names
     * @return an <code>Iterator</code> over all values matching these headers
     */
    public java.util.Iterator getMatchingMimeHeaders( final String[] match){
        return mimeHeaders.getMatchingHeaders(match);
    }

    /**
     * Get all headers that do not match.
     *
     * @param match  an array of <code>String</code>s giving mime header names
     * @return an <code>Iterator</code> over all values not matching these
     *          headers
     */
    public java.util.Iterator getNonMatchingMimeHeaders( final String[] match){
        return mimeHeaders.getNonMatchingHeaders(match);
    }

    /**
     * Sets the content of the <CODE>SOAPEnvelope</CODE> object
     * with the data from the given <CODE>Source</CODE> object.
     * @param   source javax.xml.transform.Source</CODE> object with the data to
     *     be set
     * @throws  SOAPException if there is a problem in
     *     setting the source
     * @see #getContent() getContent()
     */
    public void setContent(Source source) throws SOAPException {
        if(source == null)
            throw new SOAPException(Messages.getMessage("illegalArgumentException00"));

        // override the checks in HandlerChainImpl for JAXRPCHandler kludge
        MessageContext ctx = getMessage().getMessageContext();
        if (ctx != null) {
            ctx.setProperty(org.apache.axis.SOAPPart.ALLOW_FORM_OPTIMIZATION,
                Boolean.TRUE);
        }

        contentSource = source;
        InputSource in = org.apache.axis.utils.XMLUtils.sourceToInputSource(contentSource);
        InputStream is = in.getByteStream();
        if(is != null) {
            setCurrentMessage(is, FORM_INPUTSTREAM);
        } else {
            Reader r = in.getCharacterStream();
            if(r == null) {
                throw new SOAPException(Messages.getMessage("noCharacterOrByteStream"));
            }
            BufferedReader br = new BufferedReader(r);
            String line = null;
            StringBuffer sb = new StringBuffer();
            try {
                while((line = br.readLine()) != null) {
                    sb.append(line);
                }
            } catch (IOException e) {
                throw new SOAPException(Messages.getMessage("couldNotReadFromCharStream"), e);
            }
            setCurrentMessage(sb.toString(), FORM_STRING);
        }
    }

    /**
     * Returns the content of the SOAPEnvelope as a JAXP <CODE>
     * Source</CODE> object.
     * @return the content as a <CODE>
     *     javax.xml.transform.Source</CODE> object
     * @throws  SOAPException  if the implementation cannot
     *     convert the specified <CODE>Source</CODE> object
     * @see #setContent(javax.xml.transform.Source) setContent(javax.xml.transform.Source)
     */
    public Source getContent() throws SOAPException {
        if(contentSource == null) {
            switch(currentForm) {
                case FORM_STRING:
                    String s = (String) currentMessage;
                    contentSource = new StreamSource(new StringReader(s));
                    break;
                case FORM_INPUTSTREAM:
                    contentSource =
                            new StreamSource((InputStream) currentMessage);
                    break;
                case FORM_SOAPENVELOPE:
                    SOAPEnvelope se = (SOAPEnvelope) currentMessage;
                    try {
                        contentSource = new DOMSource(se.getAsDocument());
                    } catch (Exception e) {
                        throw new SOAPException(Messages.getMessage("errorGetDocFromSOAPEnvelope"),
                                e);
                    }
                    break;
                case FORM_OPTIMIZED:
                    try {
                        ByteArrayInputStream baos = new ByteArrayInputStream(((ByteArray) currentMessage).toByteArray());
                        contentSource = new StreamSource(baos);
                    } catch (IOException e) {
                        throw new SOAPException(Messages.getMessage("errorGetDocFromSOAPEnvelope"),
                                e);
                    }
                    break;
                case FORM_BYTES:
                    byte[] bytes = (byte[]) currentMessage;
                    contentSource =
                            new StreamSource(new ByteArrayInputStream(bytes));
                    break;
                case FORM_BODYINSTREAM:
                    contentSource =
                            new StreamSource((InputStream) currentMessage);
                    break;
            }
        }
        return contentSource;
    }

    /**
     * Retrieves all the headers for this <CODE>SOAPPart</CODE>
     * object as an iterator over the <CODE>MimeHeader</CODE>
     * objects.
     * @return an <CODE>Iterator</CODE> object with all of the Mime
     *     headers for this <CODE>SOAPPart</CODE> object
     */
    public Iterator getAllMimeHeaders() {
        return mimeHeaders.getAllHeaders();
    }

    /**
     * Changes the first header entry that matches the given
     *   header name so that its value is the given value, adding a
     *   new header with the given name and value if no existing
     *   header is a match. If there is a match, this method clears
     *   all existing values for the first header that matches and
     *   sets the given value instead. If more than one header has
     *   the given name, this method removes all of the matching
     *   headers after the first one.
     *
     *   <P>Note that RFC822 headers can contain only US-ASCII
     *   characters.</P>
     * @param  name a <CODE>String</CODE> giving the
     *     header name for which to search
     * @param  value a <CODE>String</CODE> giving the
     *     value to be set. This value will be substituted for the
     *     current value(s) of the first header that is a match if
     *     there is one. If there is no match, this value will be
     *     the value for a new <CODE>MimeHeader</CODE> object.
     * @ throws java.lang.IllegalArgumentException if
     *     there was a problem with the specified mime header name
     *     or value
     * @see #getMimeHeader(java.lang.String) getMimeHeader(java.lang.String)
     */
    public void setMimeHeader(String name, String value) {
        mimeHeaders.setHeader(name,value);
    }

    /**
     * Gets all the values of the <CODE>MimeHeader</CODE> object
     * in this <CODE>SOAPPart</CODE> object that is identified by
     * the given <CODE>String</CODE>.
     * @param   name  the name of the header; example:
     *     "Content-Type"
     * @return a <CODE>String</CODE> array giving all the values for
     *     the specified header
     * @see #setMimeHeader(java.lang.String, java.lang.String) setMimeHeader(java.lang.String, java.lang.String)
     */
    public String[] getMimeHeader(String name) {
        return mimeHeaders.getHeader(name);
    }

    /**
     * Removes all the <CODE>MimeHeader</CODE> objects for this
     * <CODE>SOAPEnvelope</CODE> object.
     */
    public void removeAllMimeHeaders() {
        mimeHeaders.removeAllHeaders();
    }

    /**
     * Removes all MIME headers that match the given name.
     * @param  header  a <CODE>String</CODE> giving
     *     the name of the MIME header(s) to be removed
     */
    public void removeMimeHeader(String header) {
        mimeHeaders.removeHeader(header);
    }

    /**
     * Gets the <CODE>SOAPEnvelope</CODE> object associated with
     * this <CODE>SOAPPart</CODE> object. Once the SOAP envelope is
     * obtained, it can be used to get its contents.
     * @return the <CODE>SOAPEnvelope</CODE> object for this <CODE>
     *     SOAPPart</CODE> object
     * @throws  SOAPException if there is a SOAP error
     */
    public javax.xml.soap.SOAPEnvelope getEnvelope() throws SOAPException {
        try {
            return getAsSOAPEnvelope();
        } catch (AxisFault af) {
            throw new SOAPException(af);
        }
    }

    /**
     *  Implementation of org.w3c.Document
     *  Most of methods will be implemented using the delgate
     *  instance of SOAPDocumentImpl
     *  This is for two reasons:
     *  - possible change of message classes, by extenstion of xerces implementation
     *  - we cannot extends SOAPPart (multiple inheritance),
     *    since it is defined as Abstract class
     * ***********************************************************
     */

    private Document document = new SOAPDocumentImpl(this);
    /**
     *  @since SAAJ 1.2
     */
    public Document getSOAPDocument(){
        if(document == null){
            document = new SOAPDocumentImpl(this);
        }
        return document;
    }

    /**
     * @return
     */
    public DocumentType getDoctype(){
        return document.getDoctype();
    }

    /**
     * @return
     */
    public DOMImplementation getImplementation(){
        return document.getImplementation();
    }

    /**
     * SOAPEnvelope is the Document Elements of this XML docuement
     */
    protected Document mDocument;

    public Element getDocumentElement()
    {
        try{
            return getEnvelope();
        }catch(SOAPException se){
            return null;
        }
    }

    /**
     *
     * @param tagName
     * @return
     * @throws DOMException
     */
    public Element createElement(String tagName) throws DOMException {
        return document.createElement(tagName);
    }

    public DocumentFragment createDocumentFragment() {
        return document.createDocumentFragment();
    }

    public Text createTextNode(String data) {
        return document.createTextNode(data);
    }

    public Comment createComment(String data){
        return document.createComment(data);
    }

    public CDATASection createCDATASection(String data) throws DOMException {
        return document.createCDATASection(data);
    }

    public ProcessingInstruction createProcessingInstruction(String target, String data)
    throws DOMException {
        return document.createProcessingInstruction(target,data);
    }

    public Attr createAttribute(String name)throws DOMException {
        return document.createAttribute(name);
    }

    public EntityReference createEntityReference(String name) throws DOMException {
        return document.createEntityReference(name);
    }

    public NodeList getElementsByTagName(String tagname) {
        return document.getElementsByTagName(tagname);
    }

    public Node importNode(Node importedNode, boolean deep)
    throws DOMException {
        return document.importNode(importedNode, deep);
    }

    public Element createElementNS(String namespaceURI, String qualifiedName)
    throws DOMException {
        return document.createElementNS(namespaceURI, qualifiedName);
    }

    public Attr createAttributeNS(String namespaceURI, String qualifiedName)
    throws DOMException {
        return document.createAttributeNS(namespaceURI, qualifiedName);
    }

    public NodeList getElementsByTagNameNS(String namespaceURI, String localName) {
        return document.getElementsByTagNameNS(namespaceURI,localName);
    }

    public Element getElementById(String elementId){
        return document.getElementById(elementId);
    }

    /////////////////////////////////////////////////////////////

    public String getEncoding()
    {
        return currentEncoding;
    }

    public  void setEncoding(String s)
    {
        currentEncoding = s;
    }

    public  boolean getStandalone()
    {
        throw new UnsupportedOperationException("Not yet implemented.71");
    }


    public  void setStandalone(boolean flag)
    {
        throw new UnsupportedOperationException("Not yet implemented.72");
    }

    public  boolean getStrictErrorChecking()
    {
        throw new UnsupportedOperationException("Not yet implemented.73");
    }


    public  void setStrictErrorChecking(boolean flag)
    {
        throw new UnsupportedOperationException("Not yet implemented. 74");
    }


    public  String getVersion()
    {
        throw new UnsupportedOperationException("Not yet implemented. 75");
    }


    public  void setVersion(String s)
    {
        throw new UnsupportedOperationException("Not yet implemented.76");
    }


    public  Node adoptNode(Node node)
    throws DOMException
    {
        throw new UnsupportedOperationException("Not yet implemented.77");
    }

    /**
     *  Node Implementation
     */

    public String getNodeName(){
        return document.getNodeName();
    }

    public String getNodeValue() throws DOMException {
        return document.getNodeValue();
    }

    public void setNodeValue(String nodeValue) throws DOMException{
        document.setNodeValue(nodeValue);
    }

    public short getNodeType() {
        return document.getNodeType();
    }

    public Node getParentNode(){
        return  document.getParentNode();
    }

    public NodeList getChildNodes() {
        return document.getChildNodes();
    }

    public Node getFirstChild() {
        return document.getFirstChild();
    }

    public Node getLastChild(){
        return document.getLastChild();
    }

    public Node getPreviousSibling(){
        return document.getPreviousSibling();
    }

    public Node getNextSibling(){
        return document.getNextSibling();
    }

    public NamedNodeMap getAttributes(){
        return document.getAttributes();
    }

    public Document getOwnerDocument(){
        return document.getOwnerDocument();
    }

    public Node insertBefore(Node newChild, Node refChild) throws DOMException {
        return document.insertBefore(newChild, refChild);
    }

    public Node replaceChild(Node newChild, Node oldChild) throws DOMException {
        return document.replaceChild(newChild, oldChild);
    }

    public Node removeChild(Node oldChild) throws DOMException {
        return document.removeChild(oldChild);
    }

    public Node appendChild(Node newChild) throws DOMException {
        return document.appendChild(newChild);
    }

    public boolean hasChildNodes(){
        return document.hasChildNodes();
    }
    public Node cloneNode(boolean deep) {
        return document.cloneNode(deep);
    }

    public void normalize(){
        document.normalize();
    }

    public boolean isSupported(String feature, String version){
        return document.isSupported(feature, version);
    }

    public String getNamespaceURI() {
        return document.getNamespaceURI();
    }

    public String getPrefix() {
        return document.getPrefix();
    }

    public void setPrefix(String prefix) throws DOMException {
        document.setPrefix(prefix);
    }
    public String getLocalName() {
        return document.getLocalName();
    }

    public boolean hasAttributes(){
        return document.hasAttributes();
    }
    
    public boolean isBodyStream() {
        return (currentForm == SOAPPart.FORM_INPUTSTREAM || currentForm == SOAPPart.FORM_BODYINSTREAM);        
    }
}

