[jbossws-issues] [JBoss JIRA] Updated: (JBWS-2026) jax-ws and saaj attachments
Thomas Diesler (JIRA)
jira-events at lists.jboss.org
Wed Apr 2 05:04:39 EDT 2008
[ http://jira.jboss.com/jira/browse/JBWS-2026?page=all ]
Thomas Diesler updated JBWS-2026:
---------------------------------
Issue Type: Bug (was: Patch)
Fix Version/s: jbossws-3.x
> jax-ws and saaj attachments
> ---------------------------
>
> Key: JBWS-2026
> URL: http://jira.jboss.com/jira/browse/JBWS-2026
> Project: JBoss Web Services
> Issue Type: Bug
> Security Level: Public(Everyone can see)
> Components: jbossws-native
> Affects Versions: jbossws-native-2.0.3
> Environment: jboss as 4.2.2 + jbossws 2.0.3
> Reporter: Mirko Ravagnan
> Fix For: jbossws-3.x
>
>
> Dear jbossws developers.
> I'm having an issue dealing with a webservice provided from a third party.
> The problem I encountered is as follows:
> 1: the service returns as output some data in the response
> and an optional attachment sent with saaj.
> 2: the attachment comes along and is stored
> in a temporary directory by jboss.
> 3: jbossws fails to identify the attachment and does not bind it
> to the response of the service.
> 4: jboss throws the unused attachment away.
> I've tracked the issue on the class CommonSoapBinding
> in class org.jboss.ws.core.
> This issue is related to the inability of the mentioned class
> to deal with attachment by id, but only by part name.
> The fact is the service provider sends attachment
> without sending the content id complete with the part name
> let me explain:
> The http headers sent with the response message do not contain
> a header [Content-Id="MyAttachment=<blablabla...>"]
> but [Content-Id="<blablabla...>"]
> Hence, method "getAttachmentFromMessage" fails to find the attachment.
> As a solution, I made some modification to that method in order
> it to deal with the requirement to handle attachments by id.
> I also modified the behaviour of the method not to throw an exception
> when it does not find the attachment it expects to find, because otherwise
> you might loose the chance to get fault text messages embedded in the service
> response, as this exception breaks the process of rebuilding the java
> representation of the soap message.
> This is reflected also in method "unbindResponseMessage".
> I'm attaching the modified java source
> so that you can have evidence of the changes
> (which have a comment "\\ m." on the right side of the line)
> Many thanks for your time
> Here is the modified source.
> /*
> * JBoss, Home of Professional Open Source
> * Copyright 2005, JBoss Inc., and individual contributors as indicated
> * by the @authors tag. See the copyright.txt in the distribution for a
> * full listing of individual contributors.
> *
> * This is free software; you can redistribute it and/or modify it
> * under the terms of the GNU Lesser General Public License as
> * published by the Free Software Foundation; either version 2.1 of
> * the License, or (at your option) any later version.
> *
> * This software is distributed in the hope that it will be useful,
> * but WITHOUT ANY WARRANTY; without even the implied warranty of
> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> * Lesser General Public License for more details.
> *
> * You should have received a copy of the GNU Lesser General Public
> * License along with this software; if not, write to the Free
> * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
> * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
> */
> package org.jboss.ws.core;
> // $Id: CommonSOAPBinding.java 5322 2007-12-14 17:58:07Z richard.opalka at jboss.com $
> import java.util.HashMap;
> import java.util.Iterator;
> import java.util.Map;
> import java.util.Set;
> import javax.activation.DataHandler;
> import javax.xml.namespace.QName;
> import javax.xml.rpc.ParameterMode;
> import javax.xml.soap.AttachmentPart;
> import javax.xml.soap.MessageFactory;
> import javax.xml.soap.Name;
> import javax.xml.soap.Node;
> import javax.xml.soap.SOAPBody;
> import javax.xml.soap.SOAPBodyElement;
> import javax.xml.soap.SOAPElement;
> import javax.xml.soap.SOAPEnvelope;
> import javax.xml.soap.SOAPException;
> import javax.xml.soap.SOAPFactory;
> import javax.xml.soap.SOAPHeader;
> import javax.xml.soap.SOAPHeaderElement;
> import javax.xml.soap.SOAPMessage;
> import javax.xml.ws.handler.MessageContext;
> import org.apache.xerces.xs.XSElementDeclaration;
> import org.apache.xerces.xs.XSTypeDefinition;
> import org.jboss.logging.Logger;
> import org.jboss.ws.Constants;
> import org.jboss.ws.WSException;
> import org.jboss.ws.core.binding.BindingException;
> import org.jboss.ws.core.jaxrpc.ParameterWrapping;
> import org.jboss.ws.core.jaxws.handler.MessageContextJAXWS;
> import org.jboss.ws.core.soap.MessageContextAssociation;
> import org.jboss.ws.core.soap.MessageFactoryImpl;
> import org.jboss.ws.core.soap.NameImpl;
> import org.jboss.ws.core.soap.SOAPBodyElementDoc;
> import org.jboss.ws.core.soap.SOAPBodyElementRpc;
> import org.jboss.ws.core.soap.SOAPBodyImpl;
> import org.jboss.ws.core.soap.SOAPContentElement;
> import org.jboss.ws.core.soap.SOAPElementImpl;
> import org.jboss.ws.core.soap.SOAPFactoryImpl;
> import org.jboss.ws.core.soap.SOAPFaultImpl;
> import org.jboss.ws.core.soap.SOAPHeaderElementImpl;
> import org.jboss.ws.core.soap.SOAPMessageImpl;
> import org.jboss.ws.core.soap.Style;
> import org.jboss.ws.core.soap.UnboundHeader;
> import org.jboss.ws.core.soap.Use;
> import org.jboss.ws.core.soap.attachment.AttachmentPartImpl;
> import org.jboss.ws.core.soap.attachment.CIDGenerator;
> import org.jboss.ws.core.utils.MimeUtils;
> import org.jboss.ws.extensions.wsrm.RMConstant;
> import org.jboss.ws.extensions.wsrm.common.RMHelper;
> import org.jboss.ws.extensions.xop.XOPContext;
> import org.jboss.ws.metadata.umdm.OperationMetaData;
> import org.jboss.ws.metadata.umdm.ParameterMetaData;
> import org.jboss.ws.metadata.umdm.TypesMetaData;
> import org.jboss.wsf.common.DOMUtils;
> import org.jboss.wsf.common.JavaUtils;
> import org.jboss.xb.binding.NamespaceRegistry;
> import org.w3c.dom.Element;
> /**
> * The SOAPBinding interface is an abstraction for the SOAP binding.
> *
> * @author Thomas.Diesler at jboss.com
> * @since 04-Jul-2006
> */
> public abstract class CommonSOAPBinding implements CommonBinding
> {
> // provide logging
> protected Logger log = Logger.getLogger(getClass());
> private boolean mtomEnabled;
> protected HeaderSource headerSource;
> /** A constant representing the identity of the SOAP 1.1 over HTTP binding. */
> public static final String SOAP11HTTP_BINDING = "http://schemas.xmlsoap.org/wsdl/soap/http";
> /** A constant representing the identity of the SOAP 1.2 over HTTP binding. */
> public static final String SOAP12HTTP_BINDING = "http://www.w3.org/2003/05/soap/bindings/HTTP/";
> /** A constant representing the identity of the SOAP 1.1 over HTTP binding with MTOM enabled by default. */
> public static final String SOAP11HTTP_MTOM_BINDING = "http://schemas.xmlsoap.org/wsdl/soap/http?mtom=true";
> /** A constant representing the identity of the SOAP 1.2 over HTTP binding with MTOM enabled by default. */
> public static final String SOAP12HTTP_MTOM_BINDING = "http://www.w3.org/2003/05/soap/bindings/HTTP/?mtom=true";
> /** The SOAP encoded Array name */
> private static final Name SOAP_ARRAY_NAME = new NameImpl("Array", Constants.PREFIX_SOAP11_ENC, Constants.URI_SOAP11_ENC);
> public CommonSOAPBinding()
> {
> }
> public MessageFactory getMessageFactory()
> {
> return new MessageFactoryImpl();
> }
> public SOAPFactory getSOAPFactory()
> {
> return new SOAPFactoryImpl();
> }
> public boolean isMTOMEnabled()
> {
> return this.mtomEnabled;
> }
> public void setMTOMEnabled(boolean flag)
> {
> this.mtomEnabled = flag;
> }
> /** Create the message */
> protected abstract MessageAbstraction createMessage(OperationMetaData opMetaData) throws SOAPException;
> /** On the client side, generate the payload from IN parameters. */
> public MessageAbstraction bindRequestMessage(OperationMetaData opMetaData, EndpointInvocation epInv, Map<QName, UnboundHeader> unboundHeaders)
> throws BindingException
> {
> if (log.isDebugEnabled())
> log.debug("bindRequestMessage: " + opMetaData.getQName());
> try
> {
> CommonMessageContext msgContext = MessageContextAssociation.peekMessageContext();
> if (msgContext == null)
> throw new WSException("MessageContext not available");
> // Disable MTOM for rpc/encoded
> if (opMetaData.isRPCEncoded())
> XOPContext.setMTOMEnabled(false);
> else XOPContext.setMTOMEnabled(isMTOMEnabled());
> // Associate current message with message context
> SOAPMessageImpl reqMessage = (SOAPMessageImpl)createMessage(opMetaData);
> msgContext.setSOAPMessage(reqMessage);
> SOAPEnvelope soapEnvelope = reqMessage.getSOAPPart().getEnvelope();
> SOAPBody soapBody = soapEnvelope.getBody();
> SOAPHeader soapHeader = soapEnvelope.getHeader();
> // Get the namespace registry
> NamespaceRegistry namespaceRegistry = msgContext.getNamespaceRegistry();
> Style style = opMetaData.getStyle();
> SOAPElement soapBodyElement = soapBody;
> if (style == Style.RPC)
> {
> boolean serialize = true;
>
> if (opMetaData.getEndpointMetaData().getConfig().getRMMetaData() != null)
> {
> // RM hack to JAX-RPC serialization
> if (RMHelper.isRMOperation(opMetaData.getQName()))
> {
> serialize = false;
> }
> }
>
> if (serialize)
> {
> QName opQName = opMetaData.getQName();
> Name opName = new NameImpl(namespaceRegistry.registerQName(opQName));
> if (log.isDebugEnabled())
> log.debug("Create RPC body element: " + opName);
> soapBodyElement = new SOAPBodyElementRpc(opName);
> soapBodyElement = (SOAPBodyElement)soapBody.addChildElement(soapBodyElement);
> // Add soap encodingStyle
> if (opMetaData.getUse() == Use.ENCODED)
> {
> String envURI = soapEnvelope.getNamespaceURI();
> String envPrefix = soapEnvelope.getPrefix();
> soapBodyElement.setAttributeNS(envURI, envPrefix + ":encodingStyle", Constants.URI_SOAP11_ENC);
> }
> }
> }
> for (ParameterMetaData paramMetaData : opMetaData.getInputParameters())
> {
> QName xmlName = paramMetaData.getXmlName();
> Object value = epInv.getRequestParamValue(xmlName);
> if (paramMetaData.isSwA())
> {
> // NOTE: swa:ref is handled by the AttachmentMarshaller callback
> CIDGenerator cidGenerator = reqMessage.getCidGenerator();
> AttachmentPart part = createAttachmentPart(paramMetaData, value, cidGenerator);
> reqMessage.addAttachmentPart(part);
> // Add the attachment to the standard property
> if (value instanceof DataHandler && msgContext instanceof MessageContextJAXWS)
> {
> DataHandler dataHandler = (DataHandler)value;
> Map<String, DataHandler> attachments = (Map<String, DataHandler>)msgContext.get(MessageContext.OUTBOUND_MESSAGE_ATTACHMENTS);
> attachments.put(dataHandler.getContentType(), dataHandler);
> }
> }
> else
> {
> SOAPElement soapElement = paramMetaData.isInHeader() ? (SOAPElement)soapHeader : soapBodyElement;
> addParameterToMessage(paramMetaData, value, soapElement);
> }
> }
> // Add unbound headers
> if (unboundHeaders != null)
> {
> Iterator it = unboundHeaders.values().iterator();
> while (it.hasNext())
> {
> UnboundHeader unboundHeader = (UnboundHeader)it.next();
> if (unboundHeader.getMode() != ParameterMode.OUT)
> {
> QName xmlName = unboundHeader.getXmlName();
> Object value = unboundHeader.getHeaderValue();
> xmlName = namespaceRegistry.registerQName(xmlName);
> Name soapName = new NameImpl(xmlName.getLocalPart(), xmlName.getPrefix(), xmlName.getNamespaceURI());
> log.debug("Add unboundHeader element: " + soapName);
> SOAPContentElement contentElement = new SOAPHeaderElementImpl(soapName);
> contentElement.setParamMetaData(unboundHeader.toParameterMetaData(opMetaData));
>
> if (soapHeader == null)
> soapHeader = soapEnvelope.addHeader();
>
> soapHeader.addChildElement(contentElement);
> contentElement.setObjectValue(value);
> }
> }
> }
> // Set the SOAPAction
> setSOAPActionHeader(opMetaData, reqMessage);
> return reqMessage;
> }
> catch (Exception e)
> {
> handleException(e);
> return null;
> }
> }
> /** Override to set the SOAPAction header */
> public abstract void setSOAPActionHeader(OperationMetaData opMetaData, SOAPMessage reqMessage);
> /** On the server side, extract the IN parameters from the payload and populate an Invocation object */
> public EndpointInvocation unbindRequestMessage(OperationMetaData opMetaData, MessageAbstraction payload) throws BindingException
> {
> if (log.isDebugEnabled())
> log.debug("unbindRequestMessage: " + opMetaData.getQName());
> try
> {
> // Read the SOAPEnvelope from the reqMessage
> SOAPMessageImpl reqMessage = (SOAPMessageImpl)payload;
> SOAPEnvelope soapEnvelope = reqMessage.getSOAPPart().getEnvelope();
> SOAPHeader soapHeader = soapEnvelope.getHeader();
> SOAPBody soapBody = soapEnvelope.getBody();
> // Verify the SOAP version
> verifySOAPVersion(opMetaData, soapEnvelope);
> // Construct the endpoint invocation object
> EndpointInvocation epInv = new EndpointInvocation(opMetaData);
> CommonMessageContext msgContext = MessageContextAssociation.peekMessageContext();
> if (msgContext == null)
> throw new WSException("MessageContext not available");
> // Disable MTOM for rpc/encoded
> if (opMetaData.isRPCEncoded())
> msgContext.put(StubExt.PROPERTY_MTOM_ENABLED, Boolean.FALSE);
> // Get the namespace registry
> NamespaceRegistry namespaceRegistry = msgContext.getNamespaceRegistry();
> if (opMetaData.isMessageEndpoint() == false)
> {
> Style style = opMetaData.getStyle();
> SOAPElement payloadParent = soapBody;
> if (style == Style.RPC)
> {
> payloadParent = null;
> Iterator it = soapBody.getChildElements();
> while (payloadParent == null && it.hasNext())
> {
> Object childNode = it.next();
> if (childNode instanceof SOAPElement)
> {
> payloadParent = (SOAPElement)childNode;
> }
> }
>
> if (RMHelper.isRMOperation(opMetaData.getQName()) == false) // RM hack
> {
> if (payloadParent == null)
> throw new SOAPException("Cannot find RPC element in");
> QName elName = payloadParent.getElementQName();
> elName = namespaceRegistry.registerQName(elName);
> }
> }
> int numParameters = 0;
> for (ParameterMetaData paramMetaData : opMetaData.getParameters())
> {
> QName xmlName = paramMetaData.getXmlName();
> if (paramMetaData.getMode() == ParameterMode.OUT)
> {
> epInv.setRequestParamValue(xmlName, null);
> }
> else
> {
> if (paramMetaData.isSwA())
> {
> AttachmentPart part = getAttachmentFromMessage(paramMetaData, reqMessage);
> epInv.setRequestParamValue(xmlName, part);
> // Add the attachment to the standard property
> if (part.getDataHandler() != null && msgContext instanceof MessageContextJAXWS)
> {
> DataHandler dataHandler = part.getDataHandler();
> Map<String, DataHandler> attachments = (Map<String, DataHandler>)msgContext.get(MessageContext.INBOUND_MESSAGE_ATTACHMENTS);
> attachments.put(part.getContentId(), dataHandler);
> }
> }
> else
> {
> boolean isHeader = paramMetaData.isInHeader();
> SOAPElement element = isHeader ? soapHeader : payloadParent;
> if (!isHeader)
> numParameters++;
> SOAPContentElement value = getParameterFromMessage(paramMetaData, element, false);
> epInv.setRequestParamValue(xmlName, value);
> }
> }
> }
> if (RMHelper.isRMOperation(opMetaData.getQName()) == false)
> {
> // Verify the numer of parameters matches the actual message payload
> int numChildElements = 0;
> Iterator itElements = payloadParent.getChildElements();
> while (itElements.hasNext())
> {
> Node node = (Node)itElements.next();
> if (node instanceof SOAPElement)
> numChildElements++;
> }
> if (numChildElements != numParameters)
> throw new WSException("Invalid number of payload elements: " + numChildElements);
> }
> }
> // Generic message endpoint
> else
> {
> for (ParameterMetaData paramMetaData : opMetaData.getParameters())
> {
> QName xmlName = paramMetaData.getXmlName();
> Object value = soapBody.getChildElements().next();
> epInv.setRequestParamValue(xmlName, value);
> }
> }
> return epInv;
> }
> catch (Exception e)
> {
> handleException(e);
> return null;
> }
> }
> /** On the server side, generate the payload from OUT parameters. */
> public MessageAbstraction bindResponseMessage(OperationMetaData opMetaData, EndpointInvocation epInv) throws BindingException
> {
> if (log.isDebugEnabled())
> log.debug("bindResponseMessage: " + opMetaData.getQName());
> try
> {
> CommonMessageContext msgContext = MessageContextAssociation.peekMessageContext();
> if (msgContext == null)
> throw new WSException("MessageContext not available");
> // Disable MTOM for rpc/encoded
> if (opMetaData.isRPCEncoded())
> XOPContext.setMTOMEnabled(false);
> else XOPContext.setMTOMEnabled(isMTOMEnabled());
> // Associate current message with message context
> SOAPMessageImpl resMessage = (SOAPMessageImpl)createMessage(opMetaData);
> msgContext.setSOAPMessage(resMessage);
> // R2714 For one-way operations, an INSTANCE MUST NOT return a HTTP response that contains a SOAP envelope.
> // Specifically, the HTTP response entity-body must be empty.
> boolean isWsrmMessage = msgContext.get(RMConstant.RESPONSE_CONTEXT) != null;
> if (opMetaData.isOneWay() && (false == isWsrmMessage))
> {
> resMessage.getSOAPPart().setContent(null);
> return resMessage;
> }
> SOAPEnvelope soapEnvelope = resMessage.getSOAPPart().getEnvelope();
> SOAPHeader soapHeader = soapEnvelope.getHeader();
> SOAPBody soapBody = soapEnvelope.getBody();
> // Get the namespace registry
> NamespaceRegistry namespaceRegistry = msgContext.getNamespaceRegistry();
> Style style = opMetaData.getStyle();
> SOAPElement soapBodyElement = soapBody;
> if (style == Style.RPC)
> {
> QName opQName = opMetaData.getResponseName();
> if (false == RMHelper.isRMOperation(opQName)) // RM hack
> {
> Name opName = new NameImpl(namespaceRegistry.registerQName(opQName));
> soapBodyElement = new SOAPBodyElementRpc(opName);
> soapBodyElement = (SOAPBodyElement)soapBody.addChildElement(soapBodyElement);
> // Add soap encodingStyle
> if (opMetaData.getUse() == Use.ENCODED)
> {
> String envURI = soapEnvelope.getNamespaceURI();
> String envPrefix = soapEnvelope.getPrefix();
> soapBodyElement.setAttributeNS(envURI, envPrefix + ":encodingStyle", Constants.URI_SOAP11_ENC);
> }
> }
> }
> // Add the return to the message
> ParameterMetaData retMetaData = opMetaData.getReturnParameter();
> if (retMetaData != null)
> {
> Object value = epInv.getReturnValue();
> // TODO calls to ParameterWrapping should be elsewhere
> if (opMetaData.isDocumentWrapped())
> value = ParameterWrapping.wrapResponseParameters(retMetaData, value, epInv.getOutParameters());
> if (retMetaData.isSwA())
> {
> CIDGenerator cidGenerator = resMessage.getCidGenerator();
> AttachmentPart part = createAttachmentPart(retMetaData, value, cidGenerator);
> resMessage.addAttachmentPart(part);
> epInv.setReturnValue(part);
> // Add the attachment to the standard property
> if (part.getDataHandler() != null && msgContext instanceof MessageContextJAXWS)
> {
> DataHandler dataHandler = part.getDataHandler();
> Map<String, DataHandler> attachments = (Map<String, DataHandler>)msgContext.get(MessageContext.OUTBOUND_MESSAGE_ATTACHMENTS);
> attachments.put(part.getContentId(), dataHandler);
> }
> }
> else
> {
> SOAPContentElement soapElement = addParameterToMessage(retMetaData, value, soapBodyElement);
> epInv.setReturnValue(soapElement);
> soapElement.setObjectValue(value);
> }
> }
> // Add the out parameters to the message
> for (ParameterMetaData paramMetaData : opMetaData.getOutputParameters())
> {
> QName xmlName = paramMetaData.getXmlName();
> Object value = epInv.getResponseParamValue(xmlName);
> if (paramMetaData.isSwA())
> {
> CIDGenerator cidGenerator = resMessage.getCidGenerator();
> AttachmentPart part = createAttachmentPart(paramMetaData, value, cidGenerator);
> resMessage.addAttachmentPart(part);
> // Add the attachment to the standard property
> if (value instanceof DataHandler && msgContext instanceof MessageContextJAXWS)
> {
> DataHandler dataHandler = (DataHandler)value;
> Map<String, DataHandler> attachments = (Map<String, DataHandler>)msgContext.get(MessageContext.OUTBOUND_MESSAGE_ATTACHMENTS);
> attachments.put(dataHandler.getContentType(), dataHandler);
> }
> }
> else
> {
> if (paramMetaData.isInHeader())
> {
> addParameterToMessage(paramMetaData, value, soapHeader);
> }
> else
> {
> addParameterToMessage(paramMetaData, value, soapBodyElement);
> }
> }
> }
> return resMessage;
> }
> catch (Exception e)
> {
> handleException(e);
> return null;
> }
> }
> /** On the client side, extract the OUT parameters from the payload and return them to the client. */
> public void unbindResponseMessage(OperationMetaData opMetaData, MessageAbstraction payload, EndpointInvocation epInv, Map<QName, UnboundHeader> unboundHeaders)
> throws BindingException
> {
> if (log.isDebugEnabled())
> log.debug("unbindResponseMessage: " + opMetaData.getQName());
> try
> {
> // R2714 For one-way operations, an INSTANCE MUST NOT return a HTTP response that contains a SOAP envelope.
> // Specifically, the HTTP response entity-body must be empty.
> if (opMetaData.isOneWay() == true)
> {
> return;
> }
> // WS-Addressing might redirect the response, which results in an empty envelope
> SOAPMessageImpl resMessage = (SOAPMessageImpl)payload;
> SOAPEnvelope soapEnvelope = resMessage.getSOAPPart().getEnvelope();
> if (soapEnvelope == null)
> {
> return;
> }
> // Verify the SOAP version
> verifySOAPVersion(opMetaData, soapEnvelope);
> // Get the SOAP message context that is associated with the current thread
> CommonMessageContext msgContext = MessageContextAssociation.peekMessageContext();
> if (msgContext == null)
> throw new WSException("MessageContext not available");
> // Disable MTOM for rpc/encoded
> if (opMetaData.isRPCEncoded())
> msgContext.put(StubExt.PROPERTY_MTOM_ENABLED, Boolean.FALSE);
> SOAPHeader soapHeader = soapEnvelope.getHeader();
> SOAPBodyImpl soapBody = (SOAPBodyImpl)soapEnvelope.getBody();
> SOAPBodyElement soapBodyElement = soapBody.getBodyElement();
> // Translate the SOAPFault to an exception and throw it
> if (soapBodyElement instanceof SOAPFaultImpl)
> throwFaultException((SOAPFaultImpl)soapBodyElement);
> // Extract unbound OUT headers
> if (unboundHeaders != null && soapHeader != null)
> {
> Map<QName, UnboundHeader> outHeaders = new HashMap<QName, UnboundHeader>();
> Iterator itHeaderElements = soapHeader.getChildElements();
> while (itHeaderElements.hasNext())
> {
> SOAPContentElement soapHeaderElement = (SOAPHeaderElementImpl)itHeaderElements.next();
> Name elName = soapHeaderElement.getElementName();
> QName xmlName = new QName(elName.getURI(), elName.getLocalName());
> UnboundHeader unboundHeader = (UnboundHeader)unboundHeaders.get(xmlName);
> if (unboundHeader != null)
> {
> soapHeaderElement.setParamMetaData(unboundHeader.toParameterMetaData(opMetaData));
> // Do the unmarshalling
> Object value = soapHeaderElement.getObjectValue();
> unboundHeader.setHeaderValue(value);
> outHeaders.put(xmlName, unboundHeader);
> }
> }
> unboundHeaders.clear();
> unboundHeaders.putAll(outHeaders);
> }
> Style style = opMetaData.getStyle();
> SOAPElement soapElement = soapBody;
> if (style == Style.RPC)
> {
> if (soapBodyElement == null)
> throw new WSException("Cannot unbind response message with empty soap body");
> soapElement = soapBodyElement;
> }
> ParameterMetaData retMetaData = opMetaData.getReturnParameter();
> if (retMetaData != null)
> {
> if (retMetaData.isSwA())
> {
> AttachmentPart part = getAttachmentFromMessage(retMetaData, resMessage);
> epInv.setReturnValue(part);
> // Add the attachment to the standard property
> if (part.getDataHandler() != null && msgContext instanceof MessageContextJAXWS)
> {
> DataHandler dataHandler = part.getDataHandler();
> Map<String, DataHandler> attachments = (Map<String, DataHandler>)msgContext.get(MessageContext.INBOUND_MESSAGE_ATTACHMENTS);
> attachments.put(part.getContentId(), dataHandler);
> }
> }
> else
> {
> SOAPContentElement value = getParameterFromMessage(retMetaData, soapElement, false);
> epInv.setReturnValue(value);
> }
> }
> for (ParameterMetaData paramMetaData : opMetaData.getOutputParameters())
> {
> QName xmlName = paramMetaData.getXmlName();
> if (paramMetaData.isSwA())
> {
> AttachmentPart part = getAttachmentFromMessage(paramMetaData, resMessage);
> epInv.setResponseParamValue(xmlName, part);
> if (part != null) { // m.
> // Add the attachment to the standard property
> if (part.getDataHandler() != null && msgContext instanceof MessageContextJAXWS)
> {
> DataHandler dataHandler = part.getDataHandler();
> Map<String, DataHandler> attachments = (Map<String, DataHandler>)msgContext.get(MessageContext.INBOUND_MESSAGE_ATTACHMENTS);
> attachments.put(part.getContentId(), dataHandler);
> }
> } // m.
> }
> else
> {
> SOAPElement element = paramMetaData.isInHeader() ? soapHeader : soapElement;
> SOAPContentElement value = getParameterFromMessage(paramMetaData, element, false);
> epInv.setResponseParamValue(xmlName, value);
> }
> }
> }
> catch (Exception e)
> {
> handleException(e);
> }
> }
> public MessageAbstraction bindFaultMessage(Exception ex)
> {
> SOAPMessageImpl faultMessage = (SOAPMessageImpl)createFaultMessageFromException(ex);
> CommonMessageContext msgContext = MessageContextAssociation.peekMessageContext();
> if (msgContext != null)
> {
> msgContext.setSOAPMessage(faultMessage);
> }
> else
> {
> log.warn("Cannot set fault message in message context");
> }
> return faultMessage;
> }
> protected abstract SOAPMessage createFaultMessageFromException(Exception ex);
> private void verifySOAPVersion(OperationMetaData opMetaData, SOAPEnvelope soapEnvelope)
> {
> String envNS = soapEnvelope.getNamespaceURI();
> String bindingId = opMetaData.getEndpointMetaData().getBindingId();
> if (CommonSOAPBinding.SOAP11HTTP_BINDING.equals(bindingId) && Constants.NS_SOAP11_ENV.equals(envNS) == false)
> log.warn("Expected SOAP-1.1 envelope, but got: " + envNS);
> if (CommonSOAPBinding.SOAP12HTTP_BINDING.equals(bindingId) && Constants.NS_SOAP12_ENV.equals(envNS) == false)
> log.warn("Expected SOAP-1.2 envelope, but got: " + envNS);
> }
> private AttachmentPart createAttachmentPart(ParameterMetaData paramMetaData, Object value, CIDGenerator cidGenerator) throws SOAPException, BindingException
> {
> String partName = paramMetaData.getXmlName().getLocalPart();
> Set mimeTypes = paramMetaData.getMimeTypes();
> AttachmentPart part = new AttachmentPartImpl();
> if (value instanceof DataHandler)
> {
> DataHandler handler = (DataHandler)value;
> String mimeType = MimeUtils.getBaseMimeType(handler.getContentType());
> // JAX-WS 2.0, 2.6.3.1 MIME Content
> // Conformance (MIME type mismatch): On receipt of a message where the MIME type of a part does not
> // match that described in the WSDL an implementation SHOULD throw a WebServiceException.
> if (mimeTypes != null && !MimeUtils.isMemberOf(mimeType, mimeTypes))
> log.warn("Mime type " + mimeType + " not allowed for parameter " + partName + " allowed types are " + mimeTypes);
> part.setDataHandler((DataHandler)value);
> }
> else
> {
> String mimeType = null;
> if (mimeTypes != null && mimeTypes.size() > 0)
> {
> mimeType = (String)mimeTypes.iterator().next();
> }
> else
> {
> mimeType = MimeUtils.resolveMimeType(value);
> }
> if (mimeType == null)
> throw new BindingException("Could not determine mime type for attachment parameter: " + partName);
> part.setContent(value, mimeType);
> }
> if (paramMetaData.isSwA())
> {
> String swaCID = '<' + partName + "=" + cidGenerator.generateFromCount() + '>';
> part.setContentId(swaCID);
> }
> if (paramMetaData.isXOP())
> {
> String xopCID = '<' + cidGenerator.generateFromName(partName) + '>';
> part.setContentId(xopCID);
> }
> return part;
> }
> private AttachmentPart getAttachmentFromMessage(ParameterMetaData paramMetaData, SOAPMessage message) throws SOAPException, BindingException
> {
> QName xmlName = paramMetaData.getXmlName();
> AttachmentPart part = ((SOAPMessageImpl)message).getAttachmentByPartName(xmlName.getLocalPart());
> if (part == null) { // m.
> Iterator<SOAPElement> it = message.getSOAPBody().getChildElements(xmlName); // m.
> if (it.hasNext()) { // m.
> SOAPElement e = it.next(); // m.
> part = ((SOAPMessageImpl)message).getAttachment(e); // m.
> }
> }
> // m. if (part == null)
> // m. throw new BindingException("Could not locate attachment for parameter: " + paramMetaData.getXmlName());
> return part;
> }
> /** Marshall the given parameter and add it to the SOAPMessage */
> private SOAPContentElement addParameterToMessage(ParameterMetaData paramMetaData, Object value, SOAPElement soapElement) throws SOAPException, BindingException
> {
> QName xmlName = paramMetaData.getXmlName();
> Class javaType = paramMetaData.getJavaType();
> if (value != null && paramMetaData.isXOP() == false)
> {
> Class valueType = value.getClass();
> if (JavaUtils.isAssignableFrom(javaType, valueType) == false)
> throw new BindingException("javaType " + javaType.getName() + " is not assignable from: " + valueType.getName());
> }
> // Make sure we have a prefix on qualified names
> if (xmlName.getNamespaceURI().length() > 0)
> {
> CommonMessageContext msgContext = MessageContextAssociation.peekMessageContext();
> NamespaceRegistry namespaceRegistry = msgContext.getNamespaceRegistry();
> xmlName = namespaceRegistry.registerQName(xmlName);
> }
> Name soapName = new NameImpl(xmlName.getLocalPart(), xmlName.getPrefix(), xmlName.getNamespaceURI());
> SOAPContentElement contentElement;
> if (soapElement instanceof SOAPHeader)
> {
> contentElement = new SOAPHeaderElementImpl(soapName);
> soapElement.addChildElement(contentElement);
> }
> else
> {
> Style style = paramMetaData.getOperationMetaData().getStyle();
> if (style == Style.DOCUMENT)
> {
> contentElement = new SOAPBodyElementDoc(soapName);
> soapElement.addChildElement(contentElement);
> }
> else
> {
> contentElement = new SOAPContentElement(soapName);
> soapElement.addChildElement(contentElement);
> }
> }
> contentElement.setParamMetaData(paramMetaData);
> if (paramMetaData.isSOAPArrayParam())
> {
> log.trace("Add parameter as SOAP encoded Array");
> contentElement.addNamespaceDeclaration(Constants.PREFIX_SOAP11_ENC, Constants.URI_SOAP11_ENC);
> }
> // When a potential xop parameter is detected and MTOM is enabled
> // we flag the SOAP message as a XOP package
> if (paramMetaData.isXOP() && XOPContext.isMTOMEnabled())
> {
> log.trace("Add parameter as XOP");
> CommonMessageContext msgContext = MessageContextAssociation.peekMessageContext();
> SOAPMessageImpl soapMessage = (SOAPMessageImpl)msgContext.getSOAPMessage();
> soapMessage.setXOPMessage(true);
> }
> else if (paramMetaData.isSwaRef())
> {
> CommonMessageContext msgContext = MessageContextAssociation.peekMessageContext();
> SOAPMessageImpl soapMessage = (SOAPMessageImpl)msgContext.getSOAPMessage();
> soapMessage.setSWARefMessage(true);
> }
> contentElement.setObjectValue(value);
> return contentElement;
> }
> /** Unmarshall a message element and add it to the parameter list */
> private SOAPContentElement getParameterFromMessage(ParameterMetaData paramMetaData, SOAPElement soapElement, boolean optional) throws BindingException
> {
> Name xmlName = new NameImpl(paramMetaData.getXmlName());
> SOAPContentElement soapContentElement = null;
> Iterator childElements = soapElement.getChildElements();
> while (childElements.hasNext())
> {
> Object childNode = childElements.next();
> if (childNode instanceof SOAPElement)
> {
> SOAPElementImpl childElement = (SOAPElementImpl)childNode;
> // If this message was manipulated by a handler the child may not be a content element
> if (!(childElement instanceof SOAPContentElement))
> childElement = (SOAPContentElement)soapElement.replaceChild(new SOAPContentElement(childElement), childElement);
> // The parameters are expected to be lazy
> SOAPContentElement aux = (SOAPContentElement)childElement;
> Name elName = aux.getElementName();
> if (xmlName.equals(elName))
> {
> soapContentElement = aux;
> soapContentElement.setParamMetaData(paramMetaData);
> break;
> }
> if (SOAP_ARRAY_NAME.equals(elName))
> {
> CommonMessageContext msgContext = MessageContextAssociation.peekMessageContext();
> msgContext.put(CommonMessageContext.ALLOW_EXPAND_TO_DOM, Boolean.TRUE);
> try
> {
> QName compXMLName = paramMetaData.getXmlName();
> Element compElement = DOMUtils.getFirstChildElement(aux);
> // NPE when the soap encoded array size is 0 on the return path
> // http://jira.jboss.org/jira/browse/JBWS-1285
> if (compElement == null || compElement.getNodeName().equals(compXMLName.getLocalPart()))
> {
> soapContentElement = aux;
> soapContentElement.setParamMetaData(paramMetaData);
> break;
> }
> }
> finally
> {
> msgContext.remove(CommonMessageContext.ALLOW_EXPAND_TO_DOM);
> }
> }
> }
> }
> // If matching by name fails, try to match by xmlType
> // This maybe necessary when wsa:Action dispatches to the operation
> if (soapContentElement == null)
> {
> childElements = soapElement.getChildElements();
> OperationMetaData opMetaData = paramMetaData.getOperationMetaData();
> TypesMetaData typesMetaData = opMetaData.getEndpointMetaData().getServiceMetaData().getTypesMetaData();
> if (childElements.hasNext() && opMetaData.getStyle() == Style.DOCUMENT)
> {
> SOAPElementImpl childElement = (SOAPElementImpl)childElements.next();
> // The parameters are expected to be lazy
> SOAPContentElement aux = (SOAPContentElement)childElement;
> Name elName = aux.getElementName();
> QName elType = null;
> XSElementDeclaration xsdElement = typesMetaData.getSchemaModel().getElementDeclaration(elName.getLocalName(), elName.getURI());
> if (xsdElement != null && xsdElement.getTypeDefinition() != null)
> {
> XSTypeDefinition xsdType = xsdElement.getTypeDefinition();
> elType = new QName(xsdType.getNamespace(), xsdType.getName());
> }
> if (paramMetaData.getXmlType().equals(elType))
> {
> soapContentElement = aux;
> soapContentElement.setParamMetaData(paramMetaData);
> }
> }
> }
> if (soapContentElement == null && optional == false)
> throw new WSException("Cannot find child element: " + xmlName);
> // When a potential XOP parameter is detected and
> // the incomming request is actuall XOP encoded we flag
> // the SOAP message a XOP packaged.
> if (paramMetaData.isXOP() && XOPContext.isXOPEncodedRequest())
> {
> SOAPMessageImpl soapMessage = (SOAPMessageImpl)MessageContextAssociation.peekMessageContext().getSOAPMessage();
> soapMessage.setXOPMessage(true);
> }
> else if (paramMetaData.isSwaRef())
> {
> SOAPMessageImpl soapMessage = (SOAPMessageImpl)MessageContextAssociation.peekMessageContext().getSOAPMessage();
> soapMessage.setSWARefMessage(true);
> }
> return soapContentElement;
> }
> abstract protected void throwFaultException(SOAPFaultImpl fault) throws Exception;
> abstract protected void verifyUnderstoodHeader(SOAPHeaderElement element) throws Exception;
> public void checkMustUnderstand(OperationMetaData opMetaData) throws Exception
> {
> CommonMessageContext msgContext = MessageContextAssociation.peekMessageContext();
> if (msgContext == null)
> throw new WSException("MessageContext not available");
> SOAPMessageImpl soapMessage = (SOAPMessageImpl)msgContext.getSOAPMessage();
> SOAPEnvelope soapEnvelope = soapMessage.getSOAPPart().getEnvelope();
> if (soapEnvelope == null || soapEnvelope.getHeader() == null)
> return;
> Iterator it = soapEnvelope.getHeader().examineAllHeaderElements();
> while (it.hasNext())
> {
> SOAPHeaderElement soapHeaderElement = (SOAPHeaderElement)it.next();
> Name name = soapHeaderElement.getElementName();
> QName xmlName = new QName(name.getURI(), name.getLocalName());
> ParameterMetaData paramMetaData = (opMetaData != null ? opMetaData.getParameter(xmlName) : null);
> boolean isBoundHeader = (paramMetaData != null && paramMetaData.isInHeader());
> if (!isBoundHeader && soapHeaderElement.getMustUnderstand())
> verifyUnderstoodHeader(soapHeaderElement);
> }
> }
> public void setHeaderSource(HeaderSource source)
> {
> headerSource = source;
> }
> private void handleException(Exception ex) throws BindingException
> {
> if (ex instanceof RuntimeException)
> throw (RuntimeException)ex;
> if (ex instanceof BindingException)
> throw (BindingException)ex;
> throw new BindingException(ex);
> }
> }
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://jira.jboss.com/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
More information about the jbossws-issues
mailing list