| /* |
| * 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 <CODE>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); |
| } |
| } |
| |