/////////////////////////////////////////////////////////////////////////
//
// © University of Southampton IT Innovation Centre, 2004
//
// Copyright in this library belongs to the IT Innovation Centre of
// 2 Venture Road, Chilworth Science Park, Southampton, SO16 7NP, UK.
//
// This software may not be used, sold, licensed, transferred, copied
// or reproduced in whole or in part in any manner or form or in or
// on any media by any person other than in accordance with the terms
// of the Licence Agreement supplied with the software, or otherwise
// without the prior written consent of the copyright owners.
//
// This software is distributed WITHOUT ANY WARRANTY, without even the
// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE, except where stated in the Licence Agreement supplied with
// the software.
//
//      Created by:             Darren Marvin
//      Created date:           2003/09/19
//      Created for project:    GEMSS
//
/////////////////////////////////////////////////////////////////////////
//
//      Dependencies: None
//
/////////////////////////////////////////////////////////////////////////
//
//      Last commit info:       $Author: $
//                              $Date: $
//                              $Revision: $
//
/////////////////////////////////////////////////////////////////////////

package uk.ac.soton.itinnovation.gemss.transportmessaging.messaging;

import java.io.*;
import java.util.*;
import java.util.logging.*;
import javax.activation.*;
import javax.xml.parsers.*;
import javax.xml.soap.*;
import org.w3c.dom.*;
import uk.ac.soton.itinnovation.gemss.transportmessaging.messaging.context.*;
import uk.ac.soton.itinnovation.gemss.utils.configuration.*;

/**
 * SOAPMessage is the XML message holder for the messaging framework
 */
public class SOAPMessage implements Message {

    private static final String TEMPORARY_FILE_DIR = "gemss.transport.messaging.temp.file.dir";
    private static final String TEMP_FILE_EXT = "_tmp.dat";
    private static Logger mLogger = Logger.getLogger("uk.ac.soton.itinnovation.gemss.transportmessaging.messaging.SOAPMessage");


    private MessageContext mMessageCtx = null;
    private javax.xml.soap.SOAPMessage mWireMessage = null;
    private Map mAttachmentMap = null;
    private File mTempFile = null;
    private List inStreams = new ArrayList();;

    /**
     * Constructor forces passing of a message context only
     * @param msgCtx message context
     */
    public SOAPMessage(MessageContext msgCtx) throws MessagingException {
        try{

          if(msgCtx==null) {
            mLogger.log(Level.SEVERE,"A SOAPMessage is being created incorrectly with a null message context, please check your message processor");
            throw new MessagingException("Internal failure means cannot complete the message encoding required, logs hold further information");
          }
            mMessageCtx = msgCtx;
            //generate a SOAPEnvelope
            //I will go across to only assuming SAAJ1.2 API when Axis catches up.
            //MessageFactory msgFactory = (javax.xml.soap.MessageFactory) com.sun.xml.messaging.saaj.soap.MessageFactoryImpl.newInstance();
            MessageFactory msgFactory = null;
            try{
              msgFactory = MessageFactory.newInstance();
            }
            catch(javax.xml.soap.SOAPException ex) {
              //try to directly use the axis one
              mLogger.log(Level.INFO,"Unable to dynamically load SOAP SAAJ Provider, going to try to load Axis directly");
              try{
                msgFactory = new org.apache.axis.soap.MessageFactoryImpl();
              }
              catch(Exception e) {
                mLogger.log(Level.SEVERE,"Unable to load a suitable SOAP SAAJ Provider, please check the libraries used",e);
                throw new MessagingException("Unable to load a suitable SOAP SAAJ Provider, please check the libraries used");
              }
              if(msgFactory==null) {
                mLogger.log(Level.SEVERE,"Unable to load a suitable SOAP SAAJ Provider, please check the libraries used");
                throw new MessagingException("Unable to load a suitable SOAP SAAJ Provider, please check the libraries used");
              }
            }
            mWireMessage = msgFactory.createMessage();
        }
        catch(javax.xml.soap.SOAPException ex) {
            mLogger.log(Level.SEVERE,"Problem creating empty SOAPEnvelope document, please send a bug report including all log files",ex);
            throw new MessagingException("Problem creating empty SOAPEnvelope document, please send a bug report including all log files");
        }

    }

     private static int mMessageCount = 0;

    /**
     * Constructor enables passing of a XML message as a SOAPMessage object
     * @param envelope on the wire SOAP Message
     * @param msgCtx message context
     */

     public SOAPMessage(javax.xml.soap.SOAPMessage wireMessage, MessageContext msgCtx) throws MessagingException {
        try{
          if(wireMessage==null) {
            mLogger.log(Level.SEVERE,"A SOAPMessage is being created incorrectly with a null SAAJ SOAPMessage, please check your message processor");
            throw new MessagingException("Internal failure means cannot complete the message encoding required, logs hold further information");
          }
          if(msgCtx==null) {
            mLogger.log(Level.SEVERE,"A SOAPMessage is being created incorrectly with a null message context, please check your message processor");
            throw new MessagingException("Internal failure means cannot complete the message encoding required, logs hold further information");
          }

          mWireMessage =  wireMessage;



            mMessageCtx = msgCtx;
            //cache the datahandlers so they are not lost
            mAttachmentMap = new HashMap();
            Iterator iterator = mWireMessage.getAttachments();
            while(iterator.hasNext()) {
                AttachmentPart aP = (AttachmentPart) iterator.next();
                mAttachmentMap.put(aP.getContentId(),aP.getDataHandler());
            }
        }
        catch(javax.xml.soap.SOAPException ex) {
            mLogger.log(Level.SEVERE,"Problem creating empty SOAPEnvelope document, please send a bug report including all log files",ex);
            throw new MessagingException("Problem creating empty SOAPEnvelope document, please send a bug report including all log files");
        }
    }


/*
     public SOAPMessage(javax.xml.soap.SOAPMessage wireMessage, MessageContext msgCtx) throws MessagingException {
          try{
            org.apache.xml.security.Init.init();
            if(wireMessage==null) {
              mLogger.log(Level.SEVERE,"A SOAPMessage is being created incorrectly with a null SAAJ SOAPMessage, please check your message processor");
              throw new MessagingException("Internal failure means cannot complete the message encoding required, logs hold further information");
            }
            if(msgCtx==null) {
              mLogger.log(Level.SEVERE,"A SOAPMessage is being created incorrectly with a null message context, please check your message processor");
              throw new MessagingException("Internal failure means cannot complete the message encoding required, logs hold further information");
            }
            //would like create a dom representation as a solid representation of the SOAPPart so that Axis does not misbehave

            //cache the datahandlers so they are not lost
              mAttachmentMap = new HashMap();
              Iterator iterator = wireMessage.getAttachments();
              while(iterator.hasNext()) {
                  AttachmentPart aP = (AttachmentPart) iterator.next();
                  mAttachmentMap.put(aP.getContentId(),aP.getDataHandler());
              }
            //Document doc = getDOMPart(wireMessage);
            String soapPartStr = ((org.apache.axis.Message) wireMessage).getSOAPPartAsString();
            byte[] b = soapPartStr.getBytes();
            ByteArrayInputStream bas = new ByteArrayInputStream(b);
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            factory.setNamespaceAware(true);
            factory.setValidating(false);
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document doc = builder.parse(bas);
            org.apache.xml.security.c14n.Canonicalizer c14n = org.apache.xml.security.c14n.Canonicalizer.getInstance(org.apache.xml.security.c14n.Canonicalizer.ALGO_ID_C14N_WITH_COMMENTS);
            byte[] canonicalMessage = c14n.canonicalizeSubtree(doc);
            org.xml.sax.InputSource is = new org.xml.sax.InputSource(new java.io.ByteArrayInputStream(canonicalMessage));
            javax.xml.transform.sax.SAXSource saxSource = new javax.xml.transform.sax.SAXSource(is);
            wireMessage.getSOAPPart().setContent(saxSource);


            //javax.xml.transform.dom.DOMSource domSource = new javax.xml.transform.dom.DOMSource(doc);
            //wireMessage.getSOAPPart().setContent(domSource);


	      mWireMessage = wireMessage;
              mMessageCtx = msgCtx;

          }
          catch(javax.xml.soap.SOAPException ex) {
              mLogger.log(Level.SEVERE,"Problem creating empty SOAPEnvelope document, please send a bug report including all log files",ex);
              throw new MessagingException("Problem creating empty SOAPEnvelope document, please send a bug report including all log files");
          }
          catch(javax.xml.parsers.ParserConfigurationException ex) {
            mLogger.log(Level.SEVERE,"Problem creating empty SOAPEnvelope document, please send a bug report including all log files",ex);
              throw new MessagingException("Problem creating empty SOAPEnvelope document, please send a bug report including all log files");
          }
          catch(org.xml.sax.SAXException ex) {
            mLogger.log(Level.SEVERE,"Problem creating empty SOAPEnvelope document, please send a bug report including all log files",ex);
              throw new MessagingException("Problem creating empty SOAPEnvelope document, please send a bug report including all log files");
          }
          catch(java.io.IOException ex) {
            mLogger.log(Level.SEVERE,"Problem creating empty SOAPEnvelope document, please send a bug report including all log files",ex);
              throw new MessagingException("Problem creating empty SOAPEnvelope document, please send a bug report including all log files");
          }
          catch(org.apache.xml.security.c14n.CanonicalizationException ex) {
            mLogger.log(Level.SEVERE,"Problem creating empty SOAPEnvelope document, please send a bug report including all log files",ex);
              throw new MessagingException("Problem creating empty SOAPEnvelope document, please send a bug report including all log files");
          }
          catch(org.apache.xml.security.c14n.InvalidCanonicalizerException ex) {
            mLogger.log(Level.SEVERE,"Problem creating empty SOAPEnvelope document, please send a bug report including all log files",ex);
              throw new MessagingException("Problem creating empty SOAPEnvelope document, please send a bug report including all log files");
          }

    }
*/

    /**
     * Constructor enables passing of an input stream as the source for a DOM document
     * @return
     * @throws MessagingException
     */
    public SOAPMessage(InputStream inputStream, MessageContext msgCtx) throws MessagingException {
        try{
          if(inputStream==null) {
            mLogger.log(Level.SEVERE,"A SOAPMessage is being created incorrectly with a null, please check your message processor");
            throw new MessagingException("Internal failure means cannot complete the message encoding required, logs hold further information");
          }
          if(msgCtx==null) {
            mLogger.log(Level.SEVERE,"A SOAPMessage is being created incorrectly with a null message context, please check your message processor");
            throw new MessagingException("Internal failure means cannot complete the message encoding required, logs hold further information");
          }
          mMessageCtx = msgCtx;
            //I will go across to only assuming SAAJ1.2 API when Axis catches up.MessageFactory msgFactory = (com.sun.xml.messaging.saaj.soap.MessageFactoryImpl) com.sun.xml.messaging.saaj.soap.MessageFactoryImpl.newInstance();
            //fill in content type, might be better to just set the content type to text/xml and
            //not use the connection properties which may include stuff unrelated to mime headers
            ConnectionProperties properties = msgCtx.getConnectionProperties();

            MimeHeaders headers = new MimeHeaders();

            //you need this to convert the response headers to mime headers for the message !!!!
            Map map = properties.getProperties();
            Set keySet = map.keySet();
            Iterator iterator = keySet.iterator();
            while(iterator.hasNext()) {
                String name = (String) iterator.next();
                String value = (String) map.get(name);
                headers.addHeader(name,value);
            }


            MessageFactory msgFactory = null;
            try{
              msgFactory = MessageFactory.newInstance();
            }
            catch(javax.xml.soap.SOAPException ex) {
              //try to directly use the axis one
              mLogger.log(Level.INFO,"Unable to dynamically load SOAP SAAJ Provider, going to try to load Axis directly");
              try{
                msgFactory = new org.apache.axis.soap.MessageFactoryImpl();
              }
              catch(Exception e) {
                mLogger.log(Level.SEVERE,"Unable to load a suitable SOAP SAAJ Provider, please check the libraries used",e);
                throw new MessagingException("Unable to load a suitable SOAP SAAJ Provider, please check the libraries used");
              }
              if(msgFactory==null) {
                mLogger.log(Level.SEVERE,"Unable to load a suitable SOAP SAAJ Provider, please check the libraries used");
                throw new MessagingException("Unable to load a suitable SOAP SAAJ Provider, please check the libraries used");
              }
            }

            mWireMessage = msgFactory.createMessage(headers,inputStream);

            //cache the datahandlers so they are not lost
            mAttachmentMap = new HashMap();
            iterator = mWireMessage.getAttachments();
            while(iterator.hasNext()) {
                AttachmentPart aP = (AttachmentPart) iterator.next();

                mAttachmentMap.put(aP.getContentId(),aP.getDataHandler());
            }

        }
        catch(javax.xml.soap.SOAPException ex) {
            mLogger.log(Level.SEVERE,"Problem creating empty SOAPEnvelope document, please send a bug report including all log files",ex);
            throw new MessagingException("Problem creating empty SOAPEnvelope document, please send a bug report including all log files");
        }
        catch(java.io.IOException ex) {
            mLogger.log(Level.SEVERE,"Problem creating empty SOAPEnvelope document, please send a bug report including all log files",ex);
            throw new MessagingException("Problem creating empty SOAPEnvelope document, please send a bug report including all log files");
        }
        /*
        catch(ConfigurationException ex) {
            throw new MessagingException("Problem creating empty SOAPEnvelope document, please send a bug report including all log files");
        }
        */
    }

    /**
     * Retrieve the message context
     * @return Message context
     */
    public final MessageContext getMessageContext() throws MessagingException {
        return mMessageCtx;
    }

    /**
     * Set the message context
     * @param messageCtx message context
     */
     public void setMessageContext(MessageContext messageCtx) throws MessagingException {
       if(messageCtx==null) {
         mLogger.log(Level.SEVERE,"Trying to set the message context on a SOAPMessage with a null value, please check your message processor");
         throw new MessagingException("Internal failure means cannot complete the message encoding required, logs hold further information");
       }
       mMessageCtx = messageCtx;
     }




    public void writeTo(OutputStream outStream) throws MessagingException {
        try{
            mWireMessage.writeTo(outStream);
        }
        catch(java.io.IOException ex) {
            mLogger.log(Level.SEVERE,"Problem writing SOAPMessage to output stream",ex);
            throw new MessagingException("Problem making a stream from a message, please send a bug report including all log files");
        }
        catch(javax.xml.soap.SOAPException ex) {
            mLogger.log(Level.SEVERE,"Problem writing SOAPMessage to output stream",ex);
            throw new MessagingException("Problem making a stream from a message, please send a bug report including all log files");
        }
    }

    /**
      * Retrieves an input stream that can be used to read the contents of the message
      * @return input stream
      */
     public InputStream getInputStream() throws MessagingException {
         try{
             if(mTempFile==null)
                 writeTempFile();
             FileInputStream fsIn = new FileInputStream(mTempFile);
             inStreams.add(fsIn);
             return fsIn;
         }
         catch(javax.xml.soap.SOAPException ex) {
             mLogger.log(Level.SEVERE,"Problem creating input stream for reading SOAPMessage",ex);
            throw new MessagingException("Problem making a stream from a message, please send a bug report including all log files");
         }
         catch(java.io.IOException ex) {
             mLogger.log(Level.SEVERE,"Problem creating input stream for reading SOAPMessage",ex);
            throw new MessagingException("Problem making a stream from a message, please send a bug report including all log files");
         }
         catch(ConfigurationException ex) {
             mLogger.log(Level.SEVERE,"Problem creating input stream for reading SOAPMessage",ex);
            throw new MessagingException("Problem making a stream from a message, please send a bug report including all log files");
         }
     }

     /**
      * Retrieves the numbers of bytes making up the soap message. Returns -1 if cannot establish size (e.g. too big)
      * @return length in bytes or -1 if could not establish length
      */
     public long getByteSize() {
         try{
             if(mTempFile==null)
                 writeTempFile();
             return mTempFile.length();
         }
         catch(javax.xml.soap.SOAPException ex) {
             mLogger.log(Level.SEVERE,"Problem retrieving input stream length for reading SOAPMessage",ex);
             return -1;
         }
         catch(java.io.IOException ex) {
            mLogger.log(Level.SEVERE,"Problem retrieving input stream length for reading SOAPMessage",ex);
             return -1;
         }
         catch(ConfigurationException ex) {
             mLogger.log(Level.SEVERE,"Problem retrieving input stream length for reading SOAPMessage",ex);
            return -1;
         }
     }

     public DataHandler getDataHandlerForContentId(String contentId) throws MessagingException {
         if(mAttachmentMap==null) {
             throw new MessagingException("Could not retrieve an attachment");
         }
         Set keySet = mAttachmentMap.keySet();
         Iterator iterator = keySet.iterator();
         while(iterator.hasNext()) {
             String key = (String) iterator.next();
             if(key.equals(contentId)) {
                 return (DataHandler) mAttachmentMap.get(key);
             }
         }
         throw new MessagingException("Could not retrieve an attachment");
     }


     /**
     * Retrieve the DOM Document part of the message
     * @return DOM Document part
     */

     public org.w3c.dom.Document getDOMPart() throws MessagingException, java.io.IOException, org.xml.sax.SAXException, javax.xml.soap.SOAPException, javax.xml.parsers.ParserConfigurationException {
         Document doc = null;
         javax.xml.transform.Source source = mWireMessage.getSOAPPart().getContent();
         if(source instanceof javax.xml.transform.dom.DOMSource) {
             javax.xml.transform.dom.DOMSource dSource = (javax.xml.transform.dom.DOMSource) source;
             doc = (Document) dSource.getNode();
         }
         else if(source instanceof javax.xml.transform.sax.SAXSource) {
             //following necessary since SAXSources seem to be empty for Axis
             //write to temporary file and read in as dom
             javax.xml.transform.sax.SAXSource sSource = (javax.xml.transform.sax.SAXSource) source;
             DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
             factory.setNamespaceAware(true);
             factory.setValidating(false);
             DocumentBuilder builder = factory.newDocumentBuilder();
             org.xml.sax.InputSource is = sSource.getInputSource();
             InputStream in = is.getByteStream();
             doc = builder.parse(in);
             //set the content so that a DOM source is used
             //this seems important for signature verification
             mWireMessage.getSOAPPart().setContent(new javax.xml.transform.dom.DOMSource(doc));
             javax.xml.transform.dom.DOMSource dSource = (javax.xml.transform.dom.DOMSource) mWireMessage.getSOAPPart().getContent();
             doc = (Document) dSource.getNode();

        }
         else if(source instanceof javax.xml.transform.stream.StreamSource) {
             javax.xml.transform.stream.StreamSource sSource = (javax.xml.transform.stream.StreamSource) source;
             DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
             factory.setNamespaceAware(true);
             factory.setValidating(false);
             DocumentBuilder builder = factory.newDocumentBuilder();
             InputStream inStream = sSource.getInputStream();
             if(inStream==null) {
                 //try for a reader instead
                 Reader r = sSource.getReader();
                 if(r!=null) {
                     BufferedReader br = new BufferedReader(r);
                     String line = null;
                     StringBuffer sb = new StringBuffer();

                     while((line = br.readLine()) != null) {
                         sb.append(line);
                         sb.append("\n");
                     }
                     //following converts to bytes which is not good if the message
                     //is very large but messages should not be that large anyway if use attachments
                     ByteArrayInputStream byteInStream = new ByteArrayInputStream(sb.toString().getBytes());
                     inStream = new BufferedInputStream(byteInStream);

                 }
                 else
                     throw new MessagingException("Unable to obtain DOM representation of SOAPPart");
             }
             doc = builder.parse(inStream);
             //set the content so that a DOM source is used
             //this seems important for signature verification
             mWireMessage.getSOAPPart().setContent(new javax.xml.transform.dom.DOMSource(doc));
             javax.xml.transform.dom.DOMSource dSource = (javax.xml.transform.dom.DOMSource) mWireMessage.getSOAPPart().getContent();
             doc = (Document) dSource.getNode();

             }
         return doc;
     }

    /**
     * Retrieve the 'on wire' version of this message, it may contain no elements
     * if it has not be created yet
     * @return SOAP envelope
     */
    public final javax.xml.soap.SOAPMessage getSOAPWireMessage() throws MessagingException {
        return mWireMessage;
    }

    /**
      * Asks the message to release its internal data members, this is important
      * for very large messages.
      */
     public void release() {

         if(inStreams!=null) {
             Iterator iterator = inStreams.iterator();
             while(iterator.hasNext()) {
                 FileInputStream fsIn = (FileInputStream) iterator.next();
                 try{
                     fsIn.close();
                 }
                 catch(IOException ex) {
                     //best efforts
                 }
             }
         }

         if(mTempFile!=null) {
             if(mTempFile.exists())
                 mTempFile.delete();
             mTempFile = null;
         }

         mMessageCtx = null;
         mWireMessage = null;

     }

     public void deleteAttachments() {
         if(mAttachmentMap!=null) {
             Set set = mAttachmentMap.keySet();
             Iterator keyIterator = set.iterator();

             while(keyIterator.hasNext()) {

                 String key = (String) keyIterator.next();
                 DataHandler dataHandler = (DataHandler) mAttachmentMap.get(key);

                 //delete associated file
                 DataSource dSource = dataHandler.getDataSource();
                 if(dSource instanceof FileDataSource) {
                     FileDataSource fDSource = (FileDataSource) dSource;
                     File file = fDSource.getFile();
                     if(file.exists()) {
                         file.delete();
                     }

                 }
                 else if(dSource instanceof org.apache.axis.attachments.ManagedMemoryDataSource) {
                     org.apache.axis.attachments.ManagedMemoryDataSource mDSource =
                             (org.apache.axis.attachments.ManagedMemoryDataSource) dSource;
                     mDSource.delete();
                 }
                 mAttachmentMap.clear();
                 mAttachmentMap = null;
             }

         }
     }

     public void finalize() {
         release();
     }

     private void writeTempFile() throws javax.xml.soap.SOAPException, java.io.IOException, ConfigurationException {
         //get the temporary file directory
         String tempDir = mMessageCtx.getConfiguration().getConfigurationValue(TEMPORARY_FILE_DIR);
         String fileSeparator = System.getProperty("file.separator");
         //write to temporary file
         if(tempDir.endsWith(fileSeparator)) {
             File tempDirF = new File(tempDir);
             if(!tempDirF.exists()) {
                 mLogger.log(Level.WARNING,"Could not locate temporary directory using current directory instead");
                 tempDir = "";
             }
             mTempFile = new File(tempDir + this.toString() + TEMP_FILE_EXT);
         }
         else {
             File tempDirF = new File(tempDir);
             if(!tempDirF.exists()) {
                 mLogger.log(Level.WARNING,"Could not locate temporary directory using current directory instead");
                 tempDir = "";
                 mTempFile = new File(this.toString().replace('.','_') + TEMP_FILE_EXT);
             }
             else
                 mTempFile = new File(tempDir + fileSeparator + this.toString().replace('.','_') + TEMP_FILE_EXT);
         }

         FileOutputStream fsOut = new FileOutputStream(mTempFile);
         mWireMessage.writeTo(fsOut);
         fsOut.close();
     }
     /*
     private org.w3c.dom.Document getDOMPart(javax.xml.soap.SOAPMessage sMsg) throws MessagingException, java.io.IOException, org.xml.sax.SAXException, javax.xml.soap.SOAPException, javax.xml.parsers.ParserConfigurationException {
         Document doc = null;
         javax.xml.transform.Source source = sMsg.getSOAPPart().getContent();
         if(source instanceof javax.xml.transform.dom.DOMSource) {
             javax.xml.transform.dom.DOMSource dSource = (javax.xml.transform.dom.DOMSource) source;
             doc = (Document) dSource.getNode();
         }
         else if(source instanceof javax.xml.transform.sax.SAXSource) {
             //following necessary since SAXSources seem to be empty for Axis
             //write to temporary file and read in as dom
             javax.xml.transform.sax.SAXSource sSource = (javax.xml.transform.sax.SAXSource) source;
             DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
             factory.setNamespaceAware(true);
             factory.setValidating(false);
             DocumentBuilder builder = factory.newDocumentBuilder();
             org.xml.sax.InputSource is = sSource.getInputSource();
             InputStream in = is.getByteStream();
             doc = builder.parse(in);
             //set the content so that a DOM source is used
             //this seems important for signature verification
             sMsg.getSOAPPart().setContent(new javax.xml.transform.dom.DOMSource(doc));
             javax.xml.transform.dom.DOMSource dSource = (javax.xml.transform.dom.DOMSource) sMsg.getSOAPPart().getContent();
             doc = (Document) dSource.getNode();

        }
         else if(source instanceof javax.xml.transform.stream.StreamSource) {
             javax.xml.transform.stream.StreamSource sSource = (javax.xml.transform.stream.StreamSource) source;
             DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
             factory.setNamespaceAware(true);
             factory.setValidating(false);
             DocumentBuilder builder = factory.newDocumentBuilder();
             InputStream inStream = sSource.getInputStream();
             if(inStream==null) {
                 //try for a reader instead
                 Reader r = sSource.getReader();
                 if(r!=null) {
                     BufferedReader br = new BufferedReader(r);
                     String line = null;
                     StringBuffer sb = new StringBuffer();

                     while((line = br.readLine()) != null) {
                         sb.append(line);
                         sb.append("\n");
                     }
                     //following converts to bytes which is not good if the message
                     //is very large but messages should not be that large anyway if use attachments
                     ByteArrayInputStream byteInStream = new ByteArrayInputStream(sb.toString().getBytes());
                     inStream = new BufferedInputStream(byteInStream);

                 }
                 else
                     throw new MessagingException("Unable to obtain DOM representation of SOAPPart");
             }
             doc = builder.parse(inStream);
             //set the content so that a DOM source is used
             //this seems important for signature verification
             sMsg.getSOAPPart().setContent(new javax.xml.transform.dom.DOMSource(doc));
             javax.xml.transform.dom.DOMSource dSource = (javax.xml.transform.dom.DOMSource) sMsg.getSOAPPart().getContent();
             doc = (Document) dSource.getNode();

             }
         return doc;
     }
     */
}
