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

Quick Search    Search Deep

Source code: org/apache/axis/SOAPPart.java


1   /*
2    * Copyright 2001-2004 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.apache.axis ;
18  
19  import org.apache.axis.components.logger.LogFactory;
20  import org.apache.axis.encoding.DeserializationContext;
21  import org.apache.axis.encoding.SerializationContext;
22  import org.apache.axis.message.InputStreamBody;
23  import org.apache.axis.message.MimeHeaders;
24  import org.apache.axis.message.SOAPDocumentImpl;
25  import org.apache.axis.message.SOAPEnvelope;
26  import org.apache.axis.message.SOAPHeaderElement;
27  import org.apache.axis.transport.http.HTTPConstants;
28  import org.apache.axis.utils.ByteArray;
29  import org.apache.axis.utils.Messages;
30  import org.apache.axis.utils.SessionUtils;
31  import org.apache.axis.utils.XMLUtils;
32  import org.apache.axis.handlers.HandlerChainImpl;
33  import org.apache.commons.logging.Log;
34  import org.w3c.dom.Attr;
35  import org.w3c.dom.CDATASection;
36  import org.w3c.dom.Comment;
37  import org.w3c.dom.DOMException;
38  import org.w3c.dom.DOMImplementation;
39  import org.w3c.dom.Document;
40  import org.w3c.dom.DocumentFragment;
41  import org.w3c.dom.DocumentType;
42  import org.w3c.dom.Element;
43  import org.w3c.dom.EntityReference;
44  import org.w3c.dom.NamedNodeMap;
45  import org.w3c.dom.Node;
46  import org.w3c.dom.NodeList;
47  import org.w3c.dom.ProcessingInstruction;
48  import org.w3c.dom.Text;
49  import org.xml.sax.InputSource;
50  import org.xml.sax.SAXException;
51  
52  import javax.xml.soap.SOAPException;
53  import javax.xml.soap.SOAPMessage;
54  import javax.xml.transform.Source;
55  import javax.xml.transform.dom.DOMSource;
56  import javax.xml.transform.stream.StreamSource;
57  import java.io.BufferedOutputStream;
58  import java.io.BufferedReader;
59  import java.io.BufferedWriter;
60  import java.io.ByteArrayInputStream;
61  import java.io.ByteArrayOutputStream;
62  import java.io.IOException;
63  import java.io.InputStream;
64  import java.io.OutputStreamWriter;
65  import java.io.PrintWriter;
66  import java.io.Reader;
67  import java.io.StringReader;
68  import java.io.StringWriter;
69  import java.io.UnsupportedEncodingException;
70  import java.io.Writer;
71  import java.util.Iterator;
72  import java.util.Vector;
73  
74  /**
75   * The SOAPPart provides access to the root part of the Message which
76   * contains the envelope.
77   * <p>
78   * SOAPPart implements Part, providing common MIME operations.
79   * <p>
80   * SOAPPart also allows access to its envelope,
81   * as a string, byte[], InputStream, or SOAPEnvelope.  (This functionality
82   * used to be in Message, and has been moved here more or less verbatim
83   * pending further cleanup.)
84   *
85   * @author Rob Jellinghaus (robj@unrealities.com)
86   * @author Doug Davis (dug@us.ibm.com)
87   * @author Glen Daniels (gdaniels@allaire.com)
88   * @author Heejune Ahn (cityboy@tmax.co.kr)
89   */
90  public class SOAPPart extends javax.xml.soap.SOAPPart implements Part
91  {
92      protected static Log log =
93          LogFactory.getLog(SOAPPart.class.getName());
94  
95      public static final int FORM_STRING       = 1;
96      public static final int FORM_INPUTSTREAM  = 2;
97      public static final int FORM_SOAPENVELOPE = 3;
98      public static final int FORM_BYTES        = 4;
99      public static final int FORM_BODYINSTREAM = 5;
100     public static final int FORM_FAULT        = 6;
101     public static final int FORM_OPTIMIZED    = 7;
102     private int currentForm;
103 
104     /**
105      * property used to set SOAPEnvelope as default form
106      */
107     public static final String ALLOW_FORM_OPTIMIZATION = "axis.form.optimization";
108 
109     
110     //private Hashtable headers = new Hashtable();
111     private MimeHeaders mimeHeaders = new MimeHeaders();
112 
113     private static final String[] formNames =
114     { "", "FORM_STRING", "FORM_INPUTSTREAM", "FORM_SOAPENVELOPE",
115       "FORM_BYTES", "FORM_BODYINSTREAM", "FORM_FAULT", "FORM_OPTIMIZED" };
116 
117     /**
118      * The current representation of the SOAP contents of this part.
119      * May be a String, byte[], InputStream, or SOAPEnvelope, depending
120      * on whatever was last asked for.  (ack)
121      * <p>
122      * currentForm must have the corresponding value.
123      * <p>
124      * As someone once said:  "Just a placeholder until we figure out what the actual Message
125      * object is."
126      */
127     private Object currentMessage ;
128 
129     /**
130      * default message encoding charset
131      */
132     private String currentEncoding = "UTF-8";
133 
134     // These two fields are used for caching in getAsString and getAsBytes
135     private String currentMessageAsString = null;
136     private byte[] currentMessageAsBytes = null;
137     private org.apache.axis.message.SOAPEnvelope currentMessageAsEnvelope= null;
138 
139     /**
140      * Message object this part is tied to. Used for serialization settings.
141      */
142     private Message msgObject;
143 
144     /** Field contentSource. */
145     private Source contentSource = null;
146 
147     /**
148      * The original message.  Again, may be String, byte[], InputStream,
149      * or SOAPEnvelope.
150      */
151     // private Object originalMessage ; //free up reference  this is not in use.
152 
153     /**
154      * Create a new SOAPPart.
155      * <p>
156      * Do not call this directly!  Should only be called by Message.
157      *
158      * @param parent  the parent <code>Message</code>
159      * @param initialContents  the initial contens <code>Object</code>
160      * @param isBodyStream if the body is in a stream
161      */
162     public SOAPPart(Message parent, Object initialContents, boolean isBodyStream) {
163 
164         setMimeHeader(HTTPConstants.HEADER_CONTENT_ID , SessionUtils.generateSessionId());
165         setMimeHeader(HTTPConstants.HEADER_CONTENT_TYPE , "text/xml");
166 
167         msgObject=parent;
168         // originalMessage = initialContents;
169         int form = FORM_STRING;
170         if (initialContents instanceof SOAPEnvelope) {
171             form = FORM_SOAPENVELOPE;
172             ((SOAPEnvelope)initialContents).setOwnerDocument(this);
173         } else if (initialContents instanceof InputStream) {
174             form = isBodyStream ? FORM_BODYINSTREAM : FORM_INPUTSTREAM;
175         } else if (initialContents instanceof byte[]) {
176             form = FORM_BYTES;
177         } else if (initialContents instanceof AxisFault) {
178             form = FORM_FAULT;
179         }
180 
181         if (log.isDebugEnabled()) {
182             log.debug("Enter: SOAPPart ctor(" + formNames[form] + ")");
183         }
184 
185         setCurrentMessage(initialContents, form);
186 
187         if (log.isDebugEnabled()) {
188             log.debug("Exit: SOAPPart ctor()");
189         }
190     }
191 
192 
193     /**
194      * Get the <code>Message</code> for this <code>Part</code>.
195      *
196      * @return the <code>Message</code> for this <code>Part</code>
197      */
198     public Message getMessage(){
199       return msgObject;
200     }
201 
202     /**
203      * Set the Message for this Part.
204      * Do not call this Directly. Called by Message.
205      *
206      * @param msg  the <code>Message</code> for this part
207      */
208     public void setMessage (Message msg) {
209         this.msgObject= msg;
210     }
211 
212     /**
213      * Content type is always "text/xml" for SOAPParts.
214      *
215      * @return the content type
216      */
217     public String getContentType() {
218         return "text/xml";
219     }
220 
221     /**
222      * Get the content length for this SOAPPart.
223      * This will force buffering of the SOAPPart, but it will
224      * also cache the byte[] form of the SOAPPart.
225      *
226      * @return the content length in bytes
227      */
228     public long getContentLength() throws AxisFault {
229         saveChanges();
230         if (currentForm == FORM_OPTIMIZED) {
231             return ((ByteArray) currentMessage).size();
232         } else if (currentForm == FORM_BYTES) {
233             return ((byte[]) currentMessage).length;
234         }
235         byte[] bytes = this.getAsBytes();
236         return bytes.length;
237     }
238 
239     /**
240      * This set the SOAP Envelope for this part.
241      * <p>
242      * Note: It breaks the chicken/egg created.
243      *  I need a message to create an attachment...
244      *  From the attachment I should be able to get a reference...
245      *  I now want to edit elements in the envelope in order to
246      *    place the  attachment reference to it.
247      *  How do I now update the SOAP envelope with what I've changed?
248      *
249      * @param env   the <code>SOAPEnvelope</CODE> for this <code>SOAPPart</code>
250      */
251 
252     public void setSOAPEnvelope(org.apache.axis.message.SOAPEnvelope env){
253        setCurrentMessage(env, FORM_SOAPENVELOPE) ;
254     }
255 
256     /**
257      * Write the contents to the specified stream.
258      *
259      * @param os  the <code>java.io.OutputStream</code> to write to
260      */
261     public void writeTo(java.io.OutputStream os) throws IOException {
262         if ( currentForm == FORM_BYTES ) {
263             os.write((byte[])currentMessage);
264         } else if ( currentForm == FORM_OPTIMIZED ) {
265             ((ByteArray) currentMessage).writeTo(os);
266         } else {
267             Writer writer = new OutputStreamWriter(os, currentEncoding);
268             writer = new BufferedWriter(new PrintWriter(writer));
269             writeTo(writer);
270             writer.flush();
271         }
272     }
273 
274     /**
275      * Write the contents to the specified writer.
276      *
277      * @param writer  the <code>Writer</code> to write to
278      */
279     public void writeTo(Writer writer) throws IOException {
280         boolean inclXmlDecl = false;         
281         
282         if (msgObject.getMessageContext() != null) {    // if we have message context (JAX-RPC), write xml decl always. 
283             inclXmlDecl = true;            
284         } else {    // if we have no message context (SAAJ), write xml decl according to property.
285             try {
286                 String xmlDecl = (String)msgObject.getProperty(SOAPMessage.WRITE_XML_DECLARATION);
287                 if (xmlDecl != null && xmlDecl.equals("true")) {
288                     inclXmlDecl = true;                    
289                 }                
290             } catch (SOAPException e) {
291                 throw new IOException(e.getMessage());
292             }
293         }
294         
295         if ( currentForm == FORM_FAULT ) {
296             AxisFault env = (AxisFault)currentMessage;
297             try {
298                 SerializationContext serContext = new SerializationContext(writer, getMessage().getMessageContext()); 
299                 serContext.setSendDecl(inclXmlDecl);
300                 serContext.setEncoding(currentEncoding);
301                 env.output(serContext);
302             } catch (Exception e) {
303                 log.error(Messages.getMessage("exception00"), e);
304                 throw env;
305             }
306             return;
307         }
308 
309         if ( currentForm == FORM_SOAPENVELOPE ) {
310             SOAPEnvelope env = (SOAPEnvelope)currentMessage;
311             try {
312                 SerializationContext serContext = new SerializationContext(writer, getMessage().getMessageContext());
313                 serContext.setSendDecl(inclXmlDecl);
314                 serContext.setEncoding(currentEncoding);
315                 env.output(serContext);
316             } catch (Exception e) {
317                 throw AxisFault.makeFault(e);
318             }
319             return;
320         }
321 
322         String xml = this.getAsString();
323         if(inclXmlDecl){
324             if(!xml.startsWith("<?xml")){
325                 writer.write("<?xml version=\"1.0\" encoding=\"");
326                 writer.write(currentEncoding);
327                 writer.write("\"?>");
328             }
329         }
330         writer.write(xml);
331     }
332 
333     /**
334      * Get the current message, in whatever form it happens to be right now.
335      * Will return a String, byte[], InputStream, or SOAPEnvelope, depending
336      * on circumstances.
337      * <p>
338      * The method name is historical.
339      * TODO: rename this for clarity; should be more like getContents.
340      *
341      * @return the current content
342      */
343     public Object getCurrentMessage() {
344         return currentMessage;
345     }
346 
347     /**
348      * Set the current message
349      * @param currMsg
350      * @param form
351      */
352     public void setCurrentMessage(Object currMsg, int form) {
353       currentMessageAsString = null; //Get rid of any cached stuff this is new.
354       currentMessageAsBytes = null;
355       currentMessageAsEnvelope= null;
356       setCurrentForm(currMsg, form);
357     }
358     /**
359      * Set the current contents of this Part.
360      * The method name is historical.
361      * TODO: rename this for clarity to something more like setContents???
362      *
363      * @param currMsg  the new content of this part
364      * @param form  the form of the message
365      */
366     private void setCurrentForm(Object currMsg, int form) {
367         if (log.isDebugEnabled()) {
368             String msgStr;
369             if (currMsg instanceof String) {
370                 msgStr = (String)currMsg;
371             } else {
372                 msgStr = currMsg.getClass().getName();
373             }
374             log.debug(Messages.getMessage("setMsgForm", formNames[form],
375                     "" + msgStr));
376         }
377 
378         // only change form if allowed
379         if (isFormOptimizationAllowed()) {
380             currentMessage = currMsg;
381             currentForm = form;
382             if (currentForm == FORM_SOAPENVELOPE) {
383                     currentMessageAsEnvelope = (org.apache.axis.message.SOAPEnvelope) currMsg;
384             }
385         }
386     }
387 
388     /**
389      * check if the allow optimization flag is on
390      * @return form optimization flag
391      */ 
392     private boolean isFormOptimizationAllowed() {
393         boolean allowFormOptimization = true;
394         Message msg = getMessage();
395         if (msg != null) {
396             MessageContext ctx = msg.getMessageContext();
397             if (ctx != null) {
398                 Boolean propFormOptimization = (Boolean)ctx.getProperty(ALLOW_FORM_OPTIMIZATION);
399                 if (propFormOptimization != null) {
400                     allowFormOptimization = propFormOptimization.booleanValue();
401                 }
402             }
403         }
404         return allowFormOptimization;
405     }
406 
407     public int getCurrentForm() {
408         return currentForm;
409     }
410     
411     /**
412      * Get the contents of this Part (not the headers!), as a byte
413      * array.  This will force buffering of the message.
414      *
415      * @return an array of bytes containing a byte representation of this Part
416      * @throws AxisFault if this Part can't be serialized to the byte array
417      */
418     public byte[] getAsBytes() throws AxisFault {
419         log.debug("Enter: SOAPPart::getAsBytes");
420         if ( currentForm == FORM_OPTIMIZED ) {
421             log.debug("Exit: SOAPPart::getAsBytes");
422             try {
423                 return ((ByteArray) currentMessage).toByteArray();
424             } catch (IOException e) {
425                 throw AxisFault.makeFault(e);
426             }
427         }
428         if ( currentForm == FORM_BYTES ) {
429             log.debug("Exit: SOAPPart::getAsBytes");
430             return (byte[])currentMessage;
431         }
432 
433         if ( currentForm == FORM_BODYINSTREAM ) {
434             try {
435                 getAsSOAPEnvelope();
436             } catch (Exception e) {
437                 log.fatal(Messages.getMessage("makeEnvFail00"), e);
438                 log.debug("Exit: SOAPPart::getAsBytes");
439                 return null;
440             }
441         }
442 
443         if ( currentForm == FORM_INPUTSTREAM ) {
444             // Assumes we don't need a content length
445             try {
446                 InputStream  inp = null;
447                 byte[]  buf = null;
448                 try{
449                     inp = (InputStream) currentMessage ;
450                     ByteArrayOutputStream  baos = new ByteArrayOutputStream();
451                     buf = new byte[4096];
452                     int len ;
453                     while ( (len = inp.read(buf,0,4096)) != -1 )
454                         baos.write( buf, 0, len );
455                     buf = baos.toByteArray();
456                 }finally{
457                   if(inp != null &&
458                     currentMessage instanceof org.apache.axis.transport.http.SocketInputStream )
459                     inp.close();
460                 }
461                 setCurrentForm( buf, FORM_BYTES );
462                 log.debug("Exit: SOAPPart::getAsBytes");
463                 return (byte[])currentMessage;
464             }
465             catch( Exception e ) {
466                 log.error(Messages.getMessage("exception00"), e);
467             }
468             log.debug("Exit: SOAPPart::getAsBytes");
469             return null;
470         }
471 
472         if ( currentForm == FORM_SOAPENVELOPE ||
473              currentForm == FORM_FAULT ){
474             currentEncoding = XMLUtils.getEncoding(msgObject, null);
475             ByteArrayOutputStream baos = new ByteArrayOutputStream();
476             BufferedOutputStream os = new BufferedOutputStream(baos);
477             try {
478                 this.writeTo(os);
479                 os.flush();
480             } catch (Exception e) {
481                 throw AxisFault.makeFault(e);
482             }
483             setCurrentForm(baos.toByteArray(), FORM_BYTES);
484             if (log.isDebugEnabled()) {
485                 log.debug("Exit: SOAPPart::getAsBytes(): " + currentMessage);
486             }
487             return (byte[]) currentMessage;
488         }
489 
490         if ( currentForm == FORM_STRING ) {
491             // If the current message was already converted from
492             // a byte[] to String, return the byte[] representation
493             // (this is done to avoid unnecessary conversions)
494             if (currentMessage == currentMessageAsString &&
495                 currentMessageAsBytes != null) {
496                 if (log.isDebugEnabled()) {
497                     log.debug("Exit: SOAPPart::getAsBytes()");
498                 }
499                 return currentMessageAsBytes;
500             }
501             // Save this message in case it is requested later in getAsString
502             currentMessageAsString = (String) currentMessage;
503             try{
504                 currentEncoding = XMLUtils.getEncoding(msgObject, null);
505                 setCurrentForm( ((String)currentMessage).getBytes(currentEncoding),
506                     FORM_BYTES );
507             }catch(UnsupportedEncodingException ue){
508                setCurrentForm( ((String)currentMessage).getBytes(),
509                                FORM_BYTES );
510             }
511             currentMessageAsBytes = (byte[]) currentMessage;
512 
513             log.debug("Exit: SOAPPart::getAsBytes");
514             return (byte[])currentMessage;
515         }
516 
517         log.error(Messages.getMessage("cantConvert00", ""+currentForm));
518 
519         log.debug("Exit: SOAPPart::getAsBytes");
520         return null;
521     }
522 
523     public void saveChanges() throws AxisFault {
524         log.debug("Enter: SOAPPart::saveChanges");
525         if ( currentForm == FORM_SOAPENVELOPE ||
526              currentForm == FORM_FAULT ){
527             currentEncoding = XMLUtils.getEncoding(msgObject, null);
528             ByteArray array = new ByteArray();
529             try {
530               writeTo(array);
531                 array.flush();
532             } catch (Exception e) {
533                 throw AxisFault.makeFault(e);
534             }
535             setCurrentForm( array, FORM_OPTIMIZED );
536             if (log.isDebugEnabled()) {
537                 log.debug("Exit: SOAPPart::saveChanges(): " + currentMessage);
538             }
539         }
540     }
541     /**
542      * Get the contents of this Part (not the headers!), as a String.
543      * This will force buffering of the message.
544      *
545      * @return a <code>String</code> containing the content of this message
546      * @throws AxisFault  if there is an error serializing this part
547      */
548     public String getAsString() throws AxisFault {
549         log.debug("Enter: SOAPPart::getAsString");
550         if ( currentForm == FORM_STRING ) {
551             if (log.isDebugEnabled()) {
552                 log.debug("Exit: SOAPPart::getAsString(): " + currentMessage);
553             }
554             return (String)currentMessage;
555         }
556 
557         if ( currentForm == FORM_INPUTSTREAM ||
558              currentForm == FORM_BODYINSTREAM ) {
559             getAsBytes();
560             // Fall thru to "Bytes"
561         }
562 
563         if ( currentForm == FORM_OPTIMIZED) {
564             try {
565                 currentMessageAsBytes =
566                         ((ByteArray) currentMessage).toByteArray();
567             } catch (IOException e) {
568                 throw AxisFault.makeFault(e);
569             }
570 
571             try{
572                 setCurrentForm(new String((byte[])currentMessageAsBytes,
573                                 currentEncoding),
574                         FORM_STRING);
575             }catch(UnsupportedEncodingException ue){
576                 setCurrentForm( new String((byte[]) currentMessageAsBytes),
577                                    FORM_STRING );
578             }
579             if (log.isDebugEnabled()) {
580                 log.debug("Exit: SOAPPart::getAsString(): " + currentMessage);
581             }
582             return (String)currentMessage;
583         }
584 
585         if ( currentForm == FORM_BYTES ) {
586             // If the current message was already converted from
587             // a String to byte[], return the String representation
588             // (this is done to avoid unnecessary conversions)
589             if (currentMessage == currentMessageAsBytes &&
590                 currentMessageAsString != null) {
591                 if (log.isDebugEnabled()) {
592                     log.debug("Exit: SOAPPart::getAsString(): " + currentMessageAsString);
593                 }
594                 return currentMessageAsString;
595             }
596             
597             // Save this message in case it is requested later in getAsBytes
598             currentMessageAsBytes = (byte[]) currentMessage;
599             try{
600                 setCurrentForm(new String((byte[])currentMessage,
601                                 currentEncoding),
602                         FORM_STRING);
603             }catch(UnsupportedEncodingException ue){
604                 setCurrentForm( new String((byte[]) currentMessage),
605                                    FORM_STRING );
606             }
607             currentMessageAsString = (String) currentMessage;
608             if (log.isDebugEnabled()) {
609                 log.debug("Exit: SOAPPart::getAsString(): " + currentMessage);
610             }
611             return (String)currentMessage;
612         }
613 
614         if ( currentForm == FORM_FAULT ) {
615             StringWriter writer = new StringWriter();
616             try {
617                 this.writeTo(writer);
618             } catch (Exception e) {
619                 log.error(Messages.getMessage("exception00"), e);
620                 return null;
621             }
622             setCurrentForm(writer.getBuffer().toString(), FORM_STRING);
623             if (log.isDebugEnabled()) {
624                 log.debug("Exit: SOAPPart::getAsString(): " + currentMessage);
625             }
626             return (String)currentMessage;
627         }
628 
629         if ( currentForm == FORM_SOAPENVELOPE ) {
630             StringWriter writer = new StringWriter();
631             try {
632                 this.writeTo(writer);
633             } catch (Exception e) {
634                 throw AxisFault.makeFault(e);
635             }
636             setCurrentForm(writer.getBuffer().toString(), FORM_STRING);
637             if (log.isDebugEnabled()) {
638                 log.debug("Exit: SOAPPart::getAsString(): " + currentMessage);
639             }
640             return (String)currentMessage;
641         }
642 
643         log.error( Messages.getMessage("cantConvert01", ""+currentForm));
644 
645         log.debug("Exit: SOAPPart::getAsString()");
646         return null;
647     }
648 
649     /**
650      * Get the contents of this Part (not the MIME headers!), as a
651      * SOAPEnvelope.  This will force a complete parse of the
652      * message.
653      *
654      * @return a <code>SOAPEnvelope</code> containing the message content
655      * @throws AxisFault if the envelope could not be constructed
656      */
657     public SOAPEnvelope getAsSOAPEnvelope()
658         throws AxisFault
659     {
660         if (log.isDebugEnabled()) {
661             log.debug("Enter: SOAPPart::getAsSOAPEnvelope()");
662             log.debug(Messages.getMessage("currForm", formNames[currentForm]));
663         }
664         if ( currentForm == FORM_SOAPENVELOPE )
665             return (SOAPEnvelope)currentMessage;
666 
667 
668         if (currentForm == FORM_BODYINSTREAM) {
669             InputStreamBody bodyEl =
670                              new InputStreamBody((InputStream)currentMessage);
671             SOAPEnvelope env = new SOAPEnvelope();
672             env.setOwnerDocument(this);
673             env.addBodyElement(bodyEl);
674             setCurrentForm(env, FORM_SOAPENVELOPE);
675             return env;
676         }
677 
678         InputSource is;
679 
680         if ( currentForm == FORM_INPUTSTREAM ) {
681             is = new InputSource( (InputStream) currentMessage );
682             String encoding = XMLUtils.getEncoding(msgObject, null, null);
683             if (encoding != null) {
684                 currentEncoding = encoding;
685                 is.setEncoding(currentEncoding);
686             }
687         } else {
688             is = new InputSource(new StringReader(getAsString()));
689         }
690         DeserializationContext dser = new DeserializationContext(is,
691                                            getMessage().getMessageContext(),
692                                            getMessage().getMessageType());
693         dser.getEnvelope().setOwnerDocument(this);
694         // This may throw a SAXException
695         try {
696             dser.parse();
697         } catch (SAXException e) {
698             Exception real = e.getException();
699             if (real == null)
700                 real = e;
701             throw AxisFault.makeFault(real);
702         }
703 
704         SOAPEnvelope nse= dser.getEnvelope();
705         if(currentMessageAsEnvelope != null){
706           //Need to synchronize back processed header info.
707           Vector newHeaders= nse.getHeaders();
708           Vector oldHeaders= currentMessageAsEnvelope.getHeaders();
709           if( null != newHeaders && null != oldHeaders){
710            Iterator ohi= oldHeaders.iterator();
711            Iterator nhi= newHeaders.iterator();
712            while( ohi.hasNext() && nhi.hasNext()){
713              SOAPHeaderElement nhe= (SOAPHeaderElement)nhi.next();
714              SOAPHeaderElement ohe= (SOAPHeaderElement)ohi.next();
715 
716              if(ohe.isProcessed()) nhe.setProcessed(true);
717            }
718           }
719 
720         }
721 
722         setCurrentForm(nse, FORM_SOAPENVELOPE);
723 
724         log.debug("Exit: SOAPPart::getAsSOAPEnvelope");
725         SOAPEnvelope env = (SOAPEnvelope)currentMessage;
726         env.setOwnerDocument(this);
727         return env;
728     }
729 
730     /**
731      * Add the specified MIME header, as per JAXM.
732      *
733      * @param header  the header to add
734      * @param value   the value of that header
735      */
736     public void addMimeHeader (String header, String value) {
737         mimeHeaders.addHeader(header, value);
738     }
739 
740     /**
741      * Get the specified MIME header.
742      *
743      * @param header  the name of a MIME header
744      * @return the value of the first header named <code>header</code>
745      */
746     private String getFirstMimeHeader (String header) {
747         String[] values = mimeHeaders.getHeader(header);
748         if(values != null && values.length>0)
749             return values[0];
750         return null;
751     }
752 
753     /**
754      * Total size in bytes (of all content and headers, as encoded).
755     public abstract int getSize();
756      */
757 
758     /**
759      * Content location.
760      *
761      * @return the content location
762      */
763     public String getContentLocation() {
764         return getFirstMimeHeader(HTTPConstants.HEADER_CONTENT_LOCATION);
765     }
766 
767     /**
768      * Set content location.
769      *
770      * @param loc  the content location
771      */
772     public void setContentLocation(String loc) {
773         setMimeHeader(HTTPConstants.HEADER_CONTENT_LOCATION, loc);
774     }
775 
776     /**
777      * Sets Content-Id of this part.
778      *  already defined.
779      * @param newCid new Content-Id
780      */
781     public void setContentId(String newCid){
782         setMimeHeader(HTTPConstants.HEADER_CONTENT_ID,newCid);
783     }
784 
785     /**
786      * Content ID.
787      *
788      * @return the content ID
789      */
790     public String getContentId() {
791         return getFirstMimeHeader(HTTPConstants.HEADER_CONTENT_ID);
792     }
793     /**
794      * Content ID.
795      *
796      * @return the contentId reference value that should be used directly
797      * as an href in a SOAP element to reference this attachment.
798      * <B>Not part of JAX-RPC, JAX-M, SAAJ, etc. </B>
799      */
800     public String getContentIdRef() {
801       return org.apache.axis.attachments.Attachments.CIDprefix +
802          getContentId();
803     }
804 
805 
806     /**
807      * Get all headers that match.
808      *
809      * @param match  an array of <code>String</code>s giving mime header names
810      * @return an <code>Iterator</code> over all values matching these headers
811      */
812     public java.util.Iterator getMatchingMimeHeaders( final String[] match){
813         return mimeHeaders.getMatchingHeaders(match);
814     }
815 
816     /**
817      * Get all headers that do not match.
818      *
819      * @param match  an array of <code>String</code>s giving mime header names
820      * @return an <code>Iterator</code> over all values not matching these
821      *          headers
822      */
823     public java.util.Iterator getNonMatchingMimeHeaders( final String[] match){
824         return mimeHeaders.getNonMatchingHeaders(match);
825     }
826 
827     /**
828      * Sets the content of the <CODE>SOAPEnvelope</CODE> object
829      * with the data from the given <CODE>Source</CODE> object.
830      * @param   source javax.xml.transform.Source</CODE> object with the data to
831      *     be set
832      * @throws  SOAPException if there is a problem in
833      *     setting the source
834      * @see #getContent() getContent()
835      */
836     public void setContent(Source source) throws SOAPException {
837         if(source == null)
838             throw new SOAPException(Messages.getMessage("illegalArgumentException00"));
839 
840         // override the checks in HandlerChainImpl for JAXRPCHandler kludge
841         MessageContext ctx = getMessage().getMessageContext();
842         if (ctx != null) {
843             ctx.setProperty(org.apache.axis.SOAPPart.ALLOW_FORM_OPTIMIZATION,
844                 Boolean.TRUE);
845         }
846 
847         contentSource = source;
848         InputSource in = org.apache.axis.utils.XMLUtils.sourceToInputSource(contentSource);
849         InputStream is = in.getByteStream();
850         if(is != null) {
851             setCurrentMessage(is, FORM_INPUTSTREAM);
852         } else {
853             Reader r = in.getCharacterStream();
854             if(r == null) {
855                 throw new SOAPException(Messages.getMessage("noCharacterOrByteStream"));
856             }
857             BufferedReader br = new BufferedReader(r);
858             String line = null;
859             StringBuffer sb = new StringBuffer();
860             try {
861                 while((line = br.readLine()) != null) {
862                     sb.append(line);
863                 }
864             } catch (IOException e) {
865                 throw new SOAPException(Messages.getMessage("couldNotReadFromCharStream"), e);
866             }
867             setCurrentMessage(sb.toString(), FORM_STRING);
868         }
869     }
870 
871     /**
872      * Returns the content of the SOAPEnvelope as a JAXP <CODE>
873      * Source</CODE> object.
874      * @return the content as a <CODE>
875      *     javax.xml.transform.Source</CODE> object
876      * @throws  SOAPException  if the implementation cannot
877      *     convert the specified <CODE>Source</CODE> object
878      * @see #setContent(javax.xml.transform.Source) setContent(javax.xml.transform.Source)
879      */
880     public Source getContent() throws SOAPException {
881         if(contentSource == null) {
882             switch(currentForm) {
883                 case FORM_STRING:
884                     String s = (String) currentMessage;
885                     contentSource = new StreamSource(new StringReader(s));
886                     break;
887                 case FORM_INPUTSTREAM:
888                     contentSource =
889                             new StreamSource((InputStream) currentMessage);
890                     break;
891                 case FORM_SOAPENVELOPE:
892                     SOAPEnvelope se = (SOAPEnvelope) currentMessage;
893                     try {
894                         contentSource = new DOMSource(se.getAsDocument());
895                     } catch (Exception e) {
896                         throw new SOAPException(Messages.getMessage("errorGetDocFromSOAPEnvelope"),
897                                 e);
898                     }
899                     break;
900                 case FORM_OPTIMIZED:
901                     try {
902                         ByteArrayInputStream baos = new ByteArrayInputStream(((ByteArray) currentMessage).toByteArray());
903                         contentSource = new StreamSource(baos);
904                     } catch (IOException e) {
905                         throw new SOAPException(Messages.getMessage("errorGetDocFromSOAPEnvelope"),
906                                 e);
907                     }
908                     break;
909                 case FORM_BYTES:
910                     byte[] bytes = (byte[]) currentMessage;
911                     contentSource =
912                             new StreamSource(new ByteArrayInputStream(bytes));
913                     break;
914                 case FORM_BODYINSTREAM:
915                     contentSource =
916                             new StreamSource((InputStream) currentMessage);
917                     break;
918             }
919         }
920         return contentSource;
921     }
922 
923     /**
924      * Retrieves all the headers for this <CODE>SOAPPart</CODE>
925      * object as an iterator over the <CODE>MimeHeader</CODE>
926      * objects.
927      * @return an <CODE>Iterator</CODE> object with all of the Mime
928      *     headers for this <CODE>SOAPPart</CODE> object
929      */
930     public Iterator getAllMimeHeaders() {
931         return mimeHeaders.getAllHeaders();
932     }
933 
934     /**
935      * Changes the first header entry that matches the given
936      *   header name so that its value is the given value, adding a
937      *   new header with the given name and value if no existing
938      *   header is a match. If there is a match, this method clears
939      *   all existing values for the first header that matches and
940      *   sets the given value instead. If more than one header has
941      *   the given name, this method removes all of the matching
942      *   headers after the first one.
943      *
944      *   <P>Note that RFC822 headers can contain only US-ASCII
945      *   characters.</P>
946      * @param  name a <CODE>String</CODE> giving the
947      *     header name for which to search
948      * @param  value a <CODE>String</CODE> giving the
949      *     value to be set. This value will be substituted for the
950      *     current value(s) of the first header that is a match if
951      *     there is one. If there is no match, this value will be
952      *     the value for a new <CODE>MimeHeader</CODE> object.
953      * @ throws java.lang.IllegalArgumentException if
954      *     there was a problem with the specified mime header name
955      *     or value
956      * @see #getMimeHeader(java.lang.String) getMimeHeader(java.lang.String)
957      */
958     public void setMimeHeader(String name, String value) {
959         mimeHeaders.setHeader(name,value);
960     }
961 
962     /**
963      * Gets all the values of the <CODE>MimeHeader</CODE> object
964      * in this <CODE>SOAPPart</CODE> object that is identified by
965      * the given <CODE>String</CODE>.
966      * @param   name  the name of the header; example:
967      *     "Content-Type"
968      * @return a <CODE>String</CODE> array giving all the values for
969      *     the specified header
970      * @see #setMimeHeader(java.lang.String, java.lang.String) setMimeHeader(java.lang.String, java.lang.String)
971      */
972     public String[] getMimeHeader(String name) {
973         return mimeHeaders.getHeader(name);
974     }
975 
976     /**
977      * Removes all the <CODE>MimeHeader</CODE> objects for this
978      * <CODE>SOAPEnvelope</CODE> object.
979      */
980     public void removeAllMimeHeaders() {
981         mimeHeaders.removeAllHeaders();
982     }
983 
984     /**
985      * Removes all MIME headers that match the given name.
986      * @param  header  a <CODE>String</CODE> giving
987      *     the name of the MIME header(s) to be removed
988      */
989     public void removeMimeHeader(String header) {
990         mimeHeaders.removeHeader(header);
991     }
992 
993     /**
994      * Gets the <CODE>SOAPEnvelope</CODE> object associated with
995      * this <CODE>SOAPPart</CODE> object. Once the SOAP envelope is
996      * obtained, it can be used to get its contents.
997      * @return the <CODE>SOAPEnvelope</CODE> object for this <CODE>
998      *     SOAPPart</CODE> object
999      * @throws  SOAPException if there is a SOAP error
1000     */
1001    public javax.xml.soap.SOAPEnvelope getEnvelope() throws SOAPException {
1002        try {
1003            return getAsSOAPEnvelope();
1004        } catch (AxisFault af) {
1005            throw new SOAPException(af);
1006        }
1007    }
1008
1009    /**
1010     *  Implementation of org.w3c.Document
1011     *  Most of methods will be implemented using the delgate
1012     *  instance of SOAPDocumentImpl
1013     *  This is for two reasons:
1014     *  - possible change of message classes, by extenstion of xerces implementation
1015     *  - we cannot extends SOAPPart (multiple inheritance),
1016     *    since it is defined as Abstract class
1017     * ***********************************************************
1018     */
1019
1020    private Document document = new SOAPDocumentImpl(this);
1021    /**
1022     *  @since SAAJ 1.2
1023     */
1024    public Document getSOAPDocument(){
1025        if(document == null){
1026            document = new SOAPDocumentImpl(this);
1027        }
1028        return document;
1029    }
1030
1031    /**
1032     * @return
1033     */
1034    public DocumentType getDoctype(){
1035        return document.getDoctype();
1036    }
1037
1038    /**
1039     * @return
1040     */
1041    public DOMImplementation getImplementation(){
1042        return document.getImplementation();
1043    }
1044
1045    /**
1046     * SOAPEnvelope is the Document Elements of this XML docuement
1047     */
1048    protected Document mDocument;
1049
1050    public Element getDocumentElement()
1051    {
1052        try{
1053            return getEnvelope();
1054        }catch(SOAPException se){
1055            return null;
1056        }
1057    }
1058
1059    /**
1060     *
1061     * @param tagName
1062     * @return
1063     * @throws DOMException
1064     */
1065    public Element createElement(String tagName) throws DOMException {
1066        return document.createElement(tagName);
1067    }
1068
1069    public DocumentFragment createDocumentFragment() {
1070        return document.createDocumentFragment();
1071    }
1072
1073    public Text createTextNode(String data) {
1074        return document.createTextNode(data);
1075    }
1076
1077    public Comment createComment(String data){
1078        return document.createComment(data);
1079    }
1080
1081    public CDATASection createCDATASection(String data) throws DOMException {
1082        return document.createCDATASection(data);
1083    }
1084
1085    public ProcessingInstruction createProcessingInstruction(String target, String data)
1086    throws DOMException {
1087        return document.createProcessingInstruction(target,data);
1088    }
1089
1090    public Attr createAttribute(String name)throws DOMException {
1091        return document.createAttribute(name);
1092    }
1093
1094    public EntityReference createEntityReference(String name) throws DOMException {
1095        return document.createEntityReference(name);
1096    }
1097
1098    public NodeList getElementsByTagName(String tagname) {
1099        return document.getElementsByTagName(tagname);
1100    }
1101
1102    public Node importNode(Node importedNode, boolean deep)
1103    throws DOMException {
1104        return document.importNode(importedNode, deep);
1105    }
1106
1107    public Element createElementNS(String namespaceURI, String qualifiedName)
1108    throws DOMException {
1109        return document.createElementNS(namespaceURI, qualifiedName);
1110    }
1111
1112    public Attr createAttributeNS(String namespaceURI, String qualifiedName)
1113    throws DOMException {
1114        return document.createAttributeNS(namespaceURI, qualifiedName);
1115    }
1116
1117    public NodeList getElementsByTagNameNS(String namespaceURI, String localName) {
1118        return document.getElementsByTagNameNS(namespaceURI,localName);
1119    }
1120
1121    public Element getElementById(String elementId){
1122        return document.getElementById(elementId);
1123    }
1124
1125    /////////////////////////////////////////////////////////////
1126
1127    public String getEncoding()
1128    {
1129        return currentEncoding;
1130    }
1131
1132    public  void setEncoding(String s)
1133    {
1134        currentEncoding = s;
1135    }
1136
1137    public  boolean getStandalone()
1138    {
1139        throw new UnsupportedOperationException("Not yet implemented.71");
1140    }
1141
1142
1143    public  void setStandalone(boolean flag)
1144    {
1145        throw new UnsupportedOperationException("Not yet implemented.72");
1146    }
1147
1148    public  boolean getStrictErrorChecking()
1149    {
1150        throw new UnsupportedOperationException("Not yet implemented.73");
1151    }
1152
1153
1154    public  void setStrictErrorChecking(boolean flag)
1155    {
1156        throw new UnsupportedOperationException("Not yet implemented. 74");
1157    }
1158
1159
1160    public  String getVersion()
1161    {
1162        throw new UnsupportedOperationException("Not yet implemented. 75");
1163    }
1164
1165
1166    public  void setVersion(String s)
1167    {
1168        throw new UnsupportedOperationException("Not yet implemented.76");
1169    }
1170
1171
1172    public  Node adoptNode(Node node)
1173    throws DOMException
1174    {
1175        throw new UnsupportedOperationException("Not yet implemented.77");
1176    }
1177
1178    /**
1179     *  Node Implementation
1180     */
1181
1182    public String getNodeName(){
1183        return document.getNodeName();
1184    }
1185
1186    public String getNodeValue() throws DOMException {
1187        return document.getNodeValue();
1188    }
1189
1190    public void setNodeValue(String nodeValue) throws DOMException{
1191        document.setNodeValue(nodeValue);
1192    }
1193
1194    public short getNodeType() {
1195        return document.getNodeType();
1196    }
1197
1198    public Node getParentNode(){
1199        return  document.getParentNode();
1200    }
1201
1202    public NodeList getChildNodes() {
1203        return document.getChildNodes();
1204    }
1205
1206    public Node getFirstChild() {
1207        return document.getFirstChild();
1208    }
1209
1210    public Node getLastChild(){
1211        return document.getLastChild();
1212    }
1213
1214    public Node getPreviousSibling(){
1215        return document.getPreviousSibling();
1216    }
1217
1218    public Node getNextSibling(){
1219        return document.getNextSibling();
1220    }
1221
1222    public NamedNodeMap getAttributes(){
1223        return document.getAttributes();
1224    }
1225
1226    public Document getOwnerDocument(){
1227        return document.getOwnerDocument();
1228    }
1229
1230    public Node insertBefore(Node newChild, Node refChild) throws DOMException {
1231        return document.insertBefore(newChild, refChild);
1232    }
1233
1234    public Node replaceChild(Node newChild, Node oldChild) throws DOMException {
1235        return document.replaceChild(newChild, oldChild);
1236    }
1237
1238    public Node removeChild(Node oldChild) throws DOMException {
1239        return document.removeChild(oldChild);
1240    }
1241
1242    public Node appendChild(Node newChild) throws DOMException {
1243        return document.appendChild(newChild);
1244    }
1245
1246    public boolean hasChildNodes(){
1247        return document.hasChildNodes();
1248    }
1249    public Node cloneNode(boolean deep) {
1250        return document.cloneNode(deep);
1251    }
1252
1253    public void normalize(){
1254        document.normalize();
1255    }
1256
1257    public boolean isSupported(String feature, String version){
1258        return document.isSupported(feature, version);
1259    }
1260
1261    public String getNamespaceURI() {
1262        return document.getNamespaceURI();
1263    }
1264
1265    public String getPrefix() {
1266        return document.getPrefix();
1267    }
1268
1269    public void setPrefix(String prefix) throws DOMException {
1270        document.setPrefix(prefix);
1271    }
1272    public String getLocalName() {
1273        return document.getLocalName();
1274    }
1275
1276    public boolean hasAttributes(){
1277        return document.hasAttributes();
1278    }
1279    
1280    public boolean isBodyStream() {
1281        return (currentForm == SOAPPart.FORM_INPUTSTREAM || currentForm == SOAPPart.FORM_BODYINSTREAM);        
1282    }
1283}
1284