You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by ff...@apache.org on 2014/02/13 10:43:25 UTC

svn commit: r1567873 - in /cxf/trunk/rt/frontend/jaxws/src: main/java/org/apache/cxf/jaxws/ test/java/org/apache/cxf/jaxws/dispatch/

Author: ffang
Date: Thu Feb 13 09:43:25 2014
New Revision: 1567873

URL: http://svn.apache.org/r1567873
Log:
[CXF-5550]CXF JAX-WS frontend DispatchImpl ignores setting of MessageContext.WSDL_OPERATION

Added:
    cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/dispatch/DispatchOpTest.java
    cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/dispatch/DispatchTest.wsdl
    cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/dispatch/OperationRequest.xml
    cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/dispatch/OperationResponse.xml
Modified:
    cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/DispatchImpl.java

Modified: cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/DispatchImpl.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/DispatchImpl.java?rev=1567873&r1=1567872&r2=1567873&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/DispatchImpl.java (original)
+++ cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/DispatchImpl.java Thu Feb 13 09:43:25 2014
@@ -308,9 +308,12 @@ public class DispatchImpl<T> implements 
             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 class DispatchImpl<T> implements 
                     }
                 }
             }
-            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 class DispatchImpl<T> implements 
                 }
 
                 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,7 +452,7 @@ public class DispatchImpl<T> implements 
         return client;
     }
     
-    private String getPayloadElementName(Element ele) {
+    private QName getPayloadElementName(Element ele) {
         XMLStreamReader xmlreader = StaxUtils.createXMLStreamReader(ele);
         DepthXMLStreamReader reader = new DepthXMLStreamReader(xmlreader);
         try {
@@ -440,14 +460,14 @@ public class DispatchImpl<T> implements 
 
                 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,12 +477,12 @@ public class DispatchImpl<T> implements 
     }
     
     
-    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
@@ -470,7 +490,7 @@ public class DispatchImpl<T> implements 
         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 @@ public class DispatchImpl<T> implements 
 
                 StaxUtils.skipToStartOfElement(reader);
 
-                return reader.getName().toString();
+                return reader.getName();
 
             }
         } catch (XMLStreamException e) {
@@ -497,14 +517,14 @@ public class DispatchImpl<T> implements 
             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 @@ public class DispatchImpl<T> implements 
                         && !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 @@ public class DispatchImpl<T> implements 
     public void close() throws IOException {
         client.destroy();
     }
-    
 }

Added: cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/dispatch/DispatchOpTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/dispatch/DispatchOpTest.java?rev=1567873&view=auto
==============================================================================
--- cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/dispatch/DispatchOpTest.java (added)
+++ cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/dispatch/DispatchOpTest.java Thu Feb 13 09:43:25 2014
@@ -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;
+        }
+    }
+}

Added: cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/dispatch/DispatchTest.wsdl
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/dispatch/DispatchTest.wsdl?rev=1567873&view=auto
==============================================================================
--- cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/dispatch/DispatchTest.wsdl (added)
+++ cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/dispatch/DispatchTest.wsdl Thu Feb 13 09:43:25 2014
@@ -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>

Added: cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/dispatch/OperationRequest.xml
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/dispatch/OperationRequest.xml?rev=1567873&view=auto
==============================================================================
--- cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/dispatch/OperationRequest.xml (added)
+++ cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/dispatch/OperationRequest.xml Thu Feb 13 09:43:25 2014
@@ -0,0 +1,25 @@
+<?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.
+-->
+
+<OperationRequest xmlns="http://cxf.apache.org/test/dispatch">
+    <in>Dispatch Test Operation Request</in>
+</OperationRequest>

Added: cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/dispatch/OperationResponse.xml
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/dispatch/OperationResponse.xml?rev=1567873&view=auto
==============================================================================
--- cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/dispatch/OperationResponse.xml (added)
+++ cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/dispatch/OperationResponse.xml Thu Feb 13 09:43:25 2014
@@ -0,0 +1,29 @@
+<?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.
+-->
+
+<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
+    <soap:Body>
+        <OperationResponse xmlns="http://cxf.apache.org/test/dispatch">
+            <out>Dispatch Test Operation Response</out>
+        </OperationResponse>
+    </soap:Body>
+</soap:Envelope>