Skip to content
Permalink
Browse files
[CXF-5550]CXF JAX-WS frontend DispatchImpl ignores setting of Message…
…Context.WSDL_OPERATION

git-svn-id: https://svn.apache.org/repos/asf/cxf/trunk@1567873 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
ffang committed Feb 13, 2014
1 parent 1429dd0 commit 2e0e4aa5c2314a3c1cf5b924ddf1a5a32f9a70a7
Show file tree
Hide file tree
Showing 5 changed files with 318 additions and 17 deletions.
@@ -308,9 +308,12 @@ public T invoke(T obj, boolean isOneWay) {
QName opName = (QName)getRequestContext().get(MessageContext.WSDL_OPERATION);
boolean findDispatchOp = Boolean.TRUE.equals(getRequestContext().get("find.dispatch.operation"));

boolean hasOpName;
if (opName == null) {
hasOpName = false;
opName = isOneWay ? INVOKE_ONEWAY_QNAME : INVOKE_QNAME;
} else {
hasOpName = true;
BindingOperationInfo bop = client.getEndpoint().getBinding()
.getBindingInfo().getOperation(opName);
if (bop == null) {
@@ -340,10 +343,10 @@ public T invoke(T obj, boolean isOneWay) {
}
}
}
Map<String, QName> payloadOPMap =
createPayloadEleOpNameMap(client.getEndpoint().getBinding().getBindingInfo());
Map<String, QName> payloadOPMap = createPayloadEleOpNameMap(
client.getEndpoint().getBinding().getBindingInfo(), hasOpName);
if (findDispatchOp && !payloadOPMap.isEmpty()) {
String payloadElementName = null;
QName payloadElementName = null;
if (obj instanceof javax.xml.transform.Source) {
XMLStreamReader reader = null;
try {
@@ -367,7 +370,24 @@ public T invoke(T obj, boolean isOneWay) {
}

if (payloadElementName != null) {
QName dispatchedOpName = payloadOPMap.get(payloadElementName);
if (hasOpName) {
// Verify the payload element against the given operation name.
// This allows graceful handling of non-standard WSDL definitions
// where different operations have the same payload element.
QName expectedElementName = payloadOPMap.get(opName.toString());
if (expectedElementName == null || !expectedElementName.toString().equals(
payloadElementName.toString())) {
// Verification of the provided operation name failed.
// Resolve the operation name from the payload element.
hasOpName = false;
payloadOPMap = createPayloadEleOpNameMap(
client.getEndpoint().getBinding().getBindingInfo(), hasOpName);
}
}
QName dispatchedOpName = null;
if (!hasOpName) {
dispatchedOpName = payloadOPMap.get(payloadElementName.toString());
}
if (null != dispatchedOpName) {
BindingOperationInfo dbop = client.getEndpoint().getBinding().getBindingInfo()
.getOperation(dispatchedOpName);
@@ -432,22 +452,22 @@ public Client getClient() {
return client;
}

private String getPayloadElementName(Element ele) {
private QName getPayloadElementName(Element ele) {
XMLStreamReader xmlreader = StaxUtils.createXMLStreamReader(ele);
DepthXMLStreamReader reader = new DepthXMLStreamReader(xmlreader);
try {
if (this.mode == Service.Mode.PAYLOAD) {

StaxUtils.skipToStartOfElement(reader);

return reader.getName().toString();
return reader.getName();
}
if (this.mode == Service.Mode.MESSAGE) {
StaxUtils.skipToStartOfElement(reader);
StaxUtils.toNextTag(reader,
new QName(ele.getNamespaceURI(), "Body"));
reader.nextTag();
return reader.getName().toString();
return reader.getName();
}
} catch (XMLStreamException e) {
// ignore
@@ -457,20 +477,20 @@ private String getPayloadElementName(Element ele) {
}


private String getPayloadElementName(SOAPMessage soapMessage) {
private QName getPayloadElementName(SOAPMessage soapMessage) {
try {
// we only care about the first element node, not text nodes
Element element = DOMUtils.getFirstElement(SAAJUtils.getBody(soapMessage));
if (element != null) {
return DOMUtils.getElementQName(element).toString();
return DOMUtils.getElementQName(element);
}
} catch (Exception e) {
//ignore
}
return null;
}

private String getPayloadElementName(Object object) {
private QName getPayloadElementName(Object object) {
JAXBDataBinding dataBinding = new JAXBDataBinding();
dataBinding.setContext(context);
DataWriter<XMLStreamWriter> dbwriter = dataBinding.createWriter(XMLStreamWriter.class);
@@ -488,7 +508,7 @@ private String getPayloadElementName(Object object) {

StaxUtils.skipToStartOfElement(reader);

return reader.getName().toString();
return reader.getName();

}
} catch (XMLStreamException e) {
@@ -497,14 +517,14 @@ private String getPayloadElementName(Object object) {
try {
StaxUtils.close(reader);
} catch (XMLStreamException e) {
// ignore
// ignore
}
StaxUtils.close(resultWriter);
}
return null;
}

private Map<String, QName> createPayloadEleOpNameMap(BindingInfo bindingInfo) {
private Map<String, QName> createPayloadEleOpNameMap(BindingInfo bindingInfo, boolean reverseMapping) {
Map<String, QName> payloadElementMap = new java.util.HashMap<String, QName>();
// assume a document binding style, which is default according to W3C spec on WSDL
String bindingStyle = "document";
@@ -526,12 +546,17 @@ private Map<String, QName> createPayloadEleOpNameMap(BindingInfo bindingInfo) {
&& !bop.getOperationInfo().getInput().getMessageParts().isEmpty()) {
QName qn = bop.getOperationInfo().getInput().getMessagePartByIndex(0)
.getElementQName();
payloadElementMap.put(qn.toString(), bop.getOperationInfo().getName());
QName op = bop.getOperationInfo().getName();
if (reverseMapping) {
payloadElementMap.put(op.toString(), qn);
} else {
payloadElementMap.put(qn.toString(), op);
}
}
} else if ("rpc".equals(operationStyle)) {
// if rpc
payloadElementMap.put(bop.getOperationInfo().getName().toString(), bop.getOperationInfo()
.getName());
QName op = bop.getOperationInfo().getName();
payloadElementMap.put(op.toString(), op);
}
}
}
@@ -541,5 +566,4 @@ private Map<String, QName> createPayloadEleOpNameMap(BindingInfo bindingInfo) {
public void close() throws IOException {
client.destroy();
}

}
@@ -0,0 +1,137 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.cxf.jaxws.dispatch;

import javax.xml.namespace.QName;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMSource;
import javax.xml.ws.Dispatch;
import javax.xml.ws.Service;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.soap.AddressingFeature;

import org.w3c.dom.Document;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.binding.soap.interceptor.AbstractSoapInterceptor;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.jaxws.AbstractJaxWsTest;
import org.apache.cxf.jaxws.DispatchImpl;
import org.apache.cxf.jaxws.MessageReplayObserver;
import org.apache.cxf.jaxws.ServiceImpl;
import org.apache.cxf.phase.Phase;
import org.apache.cxf.service.model.BindingOperationInfo;
import org.apache.cxf.service.model.EndpointInfo;
import org.apache.cxf.staxutils.StaxUtils;
import org.apache.cxf.transport.Destination;
import org.junit.Before;
import org.junit.Test;

public class DispatchOpTest extends AbstractJaxWsTest {
private final QName serviceName = new QName("http://cxf.apache.org/test/dispatch", "DispatchTest");

private final QName portName = new QName("http://cxf.apache.org/test/dispatch", "DispatchPort");

private final String address = "http://localhost:9120/SoapContext/DispatchPort";

private final QName operationName = new QName("http://cxf.apache.org/test/dispatch", "RequestResponseOperation");

private final String wsdlResource = "/org/apache/cxf/jaxws/dispatch/DispatchTest.wsdl";

private final String requestResource = "/org/apache/cxf/jaxws/dispatch/OperationRequest.xml";

private final String responseResource = "/org/apache/cxf/jaxws/dispatch/OperationResponse.xml";

private Destination d;

@Before
public void setUp() throws Exception {
EndpointInfo ei = new EndpointInfo(null, "http://schemas.xmlsoap.org/soap/http");
ei.setAddress(address);

d = localTransport.getDestination(ei, bus);
}

@Test
public void testResolveOperationWithSource() throws Exception {
ServiceImpl service =
new ServiceImpl(getBus(), getClass().getResource(wsdlResource), serviceName, null);

Dispatch<Source> disp = service.createDispatch(
portName, Source.class, Service.Mode.PAYLOAD);
disp.getRequestContext().put(MessageContext.WSDL_OPERATION, operationName);
disp.getRequestContext().put(Dispatch.ENDPOINT_ADDRESS_PROPERTY, address);

d.setMessageObserver(new MessageReplayObserver(responseResource));

BindingOperationVerifier bov = new BindingOperationVerifier();
((DispatchImpl<?>)disp).getClient().getOutInterceptors().add(bov);

Document doc = StaxUtils.read(getResourceAsStream(requestResource));
DOMSource source = new DOMSource(doc);
Source res = disp.invoke(source);
assertNotNull(res);

BindingOperationInfo boi = bov.getBindingOperationInfo();
assertNotNull(boi);

assertEquals(operationName, boi.getName());
}

@Test
public void testResolveOperationWithSourceAndWSA() throws Exception {
ServiceImpl service =
new ServiceImpl(getBus(), getClass().getResource(wsdlResource),
serviceName, null, new AddressingFeature());

Dispatch<Source> disp = service.createDispatch(
portName, Source.class, Service.Mode.PAYLOAD);
disp.getRequestContext().put(MessageContext.WSDL_OPERATION, operationName);
disp.getRequestContext().put(Dispatch.ENDPOINT_ADDRESS_PROPERTY, address);

d.setMessageObserver(new MessageReplayObserver(responseResource));

BindingOperationVerifier bov = new BindingOperationVerifier();
((DispatchImpl<?>)disp).getClient().getOutInterceptors().add(bov);

Document doc = StaxUtils.read(getResourceAsStream(requestResource));
DOMSource source = new DOMSource(doc);
Source res = disp.invoke(source);
assertNotNull(res);

BindingOperationInfo boi = bov.getBindingOperationInfo();
assertNotNull(boi);

assertEquals(operationName, boi.getName());
}

private static class BindingOperationVerifier extends AbstractSoapInterceptor {
BindingOperationInfo boi;
public BindingOperationVerifier() {
super(Phase.POST_LOGICAL);
}

public void handleMessage(SoapMessage message) throws Fault {
boi = message.getExchange().getBindingOperationInfo();
}

public BindingOperationInfo getBindingOperationInfo() {
return boi;
}
}
}
@@ -0,0 +1,86 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you 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.
-->

<definitions targetNamespace="http://cxf.apache.org/test/dispatch"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://cxf.apache.org/test/dispatch"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<types>
<xsd:schema targetNamespace="http://cxf.apache.org/test/dispatch" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="OperationRequest">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="in" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="OperationResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="out" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
</types>
<message name="opRequestMsg">
<part element="tns:OperationRequest" name="body"/>
</message>
<message name="opResponseMsg">
<part element="tns:OperationResponse" name="body"/>
</message>
<portType name="DispatchTestInterface">
<operation name="RequestResponseOperation">
<input message="tns:opRequestMsg"/>
<output message="tns:opResponseMsg"/>
</operation>
<operation name="OneWayOperation">
<input message="tns:opRequestMsg"/>
</operation>
</portType>
<wsdl:service name="DispatchTest">
<wsdl:port binding="tns:localhostBinding" name="DispatchPort">
<soap:address location="http://localhost:9120/SoapContext/DispatchPort"/>
</wsdl:port>
</wsdl:service>
<wsdl:binding name="localhostBinding" type="tns:DispatchTestInterface">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="RequestResponseOperation">
<soap:operation soapAction="RequestResponseOperation"/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="OneWayOperation">
<soap:operation soapAction="OneWayOperation"/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
</wsdl:operation>
</wsdl:binding>
</definitions>

0 comments on commit 2e0e4aa

Please sign in to comment.