diff options
2 files changed, 132 insertions, 4 deletions
diff --git a/sca-java-2.x/trunk/modules/binding-ws-runtime-jaxws/pom.xml b/sca-java-2.x/trunk/modules/binding-ws-runtime-jaxws/pom.xml index 2664642436..f0adefc38f 100644 --- a/sca-java-2.x/trunk/modules/binding-ws-runtime-jaxws/pom.xml +++ b/sca-java-2.x/trunk/modules/binding-ws-runtime-jaxws/pom.xml @@ -34,7 +34,6 @@ <groupId>org.apache.tuscany.sca</groupId> <artifactId>tuscany-core</artifactId> <version>2.0-SNAPSHOT</version> - <scope>runtime</scope> </dependency> <dependency> @@ -47,7 +46,6 @@ <groupId>org.apache.tuscany.sca</groupId> <artifactId>tuscany-assembly-xml</artifactId> <version>2.0-SNAPSHOT</version> - <scope>runtime</scope> </dependency> <dependency> diff --git a/sca-java-2.x/trunk/modules/binding-ws-runtime-jaxws/src/main/java/org/apache/tuscany/sca/binding/ws/jaxws/JAXWSBindingProvider.java b/sca-java-2.x/trunk/modules/binding-ws-runtime-jaxws/src/main/java/org/apache/tuscany/sca/binding/ws/jaxws/JAXWSBindingProvider.java index a2cef5340c..5cc9277201 100644 --- a/sca-java-2.x/trunk/modules/binding-ws-runtime-jaxws/src/main/java/org/apache/tuscany/sca/binding/ws/jaxws/JAXWSBindingProvider.java +++ b/sca-java-2.x/trunk/modules/binding-ws-runtime-jaxws/src/main/java/org/apache/tuscany/sca/binding/ws/jaxws/JAXWSBindingProvider.java @@ -18,6 +18,7 @@ */ package org.apache.tuscany.sca.binding.ws.jaxws; +import java.util.Iterator; import java.util.List; import javax.annotation.Resource; @@ -29,15 +30,21 @@ import javax.xml.soap.SOAPElement; import javax.xml.soap.SOAPException; import javax.xml.soap.SOAPFactory; import javax.xml.soap.SOAPFault; +import javax.xml.soap.SOAPHeader; import javax.xml.soap.SOAPMessage; import javax.xml.ws.Provider; +import javax.xml.ws.Service.Mode; import javax.xml.ws.ServiceMode; import javax.xml.ws.WebServiceContext; import javax.xml.ws.WebServiceProvider; -import javax.xml.ws.Service.Mode; +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Endpoint; +import org.apache.tuscany.sca.assembly.EndpointReference; import org.apache.tuscany.sca.binding.ws.WebServiceBinding; +import org.apache.tuscany.sca.binding.ws.WebServiceBindingFactory; import org.apache.tuscany.sca.core.FactoryExtensionPoint; +import org.apache.tuscany.sca.core.assembly.RuntimeAssemblyFactory; import org.apache.tuscany.sca.databinding.DataBindingExtensionPoint; import org.apache.tuscany.sca.host.http.ServletHost; import org.apache.tuscany.sca.interfacedef.InterfaceContract; @@ -54,6 +61,13 @@ import org.w3c.dom.Node; @WebServiceProvider @ServiceMode(Mode.MESSAGE) public class JAXWSBindingProvider implements Provider<SOAPMessage> { + public static final String WSA_FINAL_NAMESPACE = "http://www.w3.org/2005/08/addressing"; + public static final QName QNAME_WSA_ADDRESS = new QName(WSA_FINAL_NAMESPACE, "Address"); + public static final QName QNAME_WSA_FROM = new QName(WSA_FINAL_NAMESPACE, "From"); + public static final QName QNAME_WSA_REPLYTO = new QName(WSA_FINAL_NAMESPACE, "ReplyTo"); + public static final QName QNAME_WSA_REFERENCE_PARAMETERS = new QName(WSA_FINAL_NAMESPACE, "ReferenceParameters"); + public static final QName QNAME_WSA_MESSAGEID = new QName(WSA_FINAL_NAMESPACE, "MessageID"); + private MessageFactory messageFactory; private RuntimeEndpoint endpoint; private WebServiceBinding wsBinding; @@ -61,7 +75,9 @@ public class JAXWSBindingProvider implements Provider<SOAPMessage> { private SOAPFactory soapFactory; @Resource - private WebServiceContext context; + private WebServiceContext context; + private RuntimeAssemblyFactory assemblyFactory; + private WebServiceBindingFactory webServiceBindingFactory; public JAXWSBindingProvider(){ // to keep Axis2 JAXWS implementation happy @@ -76,6 +92,8 @@ public class JAXWSBindingProvider implements Provider<SOAPMessage> { this.soapMessageFactory = modelFactories.getFactory(javax.xml.soap.MessageFactory.class); this.soapFactory = modelFactories.getFactory(SOAPFactory.class); + this.assemblyFactory = (RuntimeAssemblyFactory)modelFactories.getFactory(AssemblyFactory.class); + this.webServiceBindingFactory = (WebServiceBindingFactory)modelFactories.getFactory(WebServiceBindingFactory.class); // soapMessageFactory = javax.xml.soap.MessageFactory.newInstance(); // soapFactory = SOAPFactory.newInstance(); @@ -156,6 +174,36 @@ public class JAXWSBindingProvider implements Provider<SOAPMessage> { requestMsg.setBody(body); requestMsg.setOperation(operation); + SOAPHeader header = request.getSOAPHeader(); + String callbackAddress = null; + if (header != null) { + callbackAddress = handleCallbackAddress( header, requestMsg ); + // Retrieve other callback-related headers + handleMessageIDHeader( header, requestMsg ); + } // end if + + // Create a from EPR to hold the details of the callback endpoint + EndpointReference from = null; + if (callbackAddress != null ) { + // Check for special (& not allowed!) WS_Addressing values + checkCallbackAddress( callbackAddress, request ); + // + from = assemblyFactory.createEndpointReference(); + Endpoint fromEndpoint = assemblyFactory.createEndpoint(); + from.setTargetEndpoint(fromEndpoint); + from.setStatus(EndpointReference.Status.WIRED_TARGET_FOUND_AND_MATCHED); + requestMsg.setFrom(from); + Endpoint callbackEndpoint = assemblyFactory.createEndpoint(); + // + WebServiceBinding cbBinding = webServiceBindingFactory.createWebServiceBinding(); + cbBinding.setURI(callbackAddress); + callbackEndpoint.setBinding(cbBinding); + // + callbackEndpoint.setURI(callbackAddress); + callbackEndpoint.setUnresolved(true); + from.setCallbackEndpoint(callbackEndpoint); + } + Message responseMsg = endpoint.invoke(operation, requestMsg); SOAPMessage response = soapMessageFactory.createMessage(); @@ -181,4 +229,86 @@ public class JAXWSBindingProvider implements Provider<SOAPMessage> { throw new ServiceRuntimeException(e); } } + private static String WS_REF_PARMS = "WS_REFERENCE_PARAMETERS"; + private String handleCallbackAddress( SOAPHeader header, Message msg ) { + String callbackAddress = null; + + Iterator<SOAPElement> it = header.getChildElements(QNAME_WSA_FROM); + SOAPElement from = it.hasNext() ? it.next() : null; + if( from == null ) { + Iterator<SOAPElement> it2 = header.getChildElements(QNAME_WSA_REPLYTO); + from = it2.hasNext() ? it2.next() : null; + } + + if (from != null) { + Iterator<SOAPElement> it2 = header.getChildElements(QNAME_WSA_ADDRESS); + SOAPElement callbackAddrElement = it2.hasNext() ? it2.next() : null; + if (callbackAddrElement != null) { + if (endpoint.getService().getInterfaceContract().getCallbackInterface() != null) { + callbackAddress = callbackAddrElement.getTextContent(); + } +// OMElement refParms = from.getFirstChildWithName(QNAME_WSA_REFERENCE_PARAMETERS); + Iterator<SOAPElement> it3 = header.getChildElements(QNAME_WSA_REFERENCE_PARAMETERS); + SOAPElement refParms = it3.hasNext() ? it3.next() : null; + if( refParms != null ) msg.getHeaders().put(WS_REF_PARMS, refParms); + } + } // end if + + return callbackAddress; + } // end method handleCallbackAddress + + private static String WS_MESSAGE_ID = "WS_MESSAGE_ID"; + /** + * Handle a SOAP wsa:MessageID header - place the contents into the Tuscany message for use by any callback + * @param header - the SOAP Headers + * @param msg - the Tuscany Message + */ + private void handleMessageIDHeader( SOAPHeader header, Message msg ) { + if( header == null ) return; + Iterator<SOAPElement> it = header.getChildElements(QNAME_WSA_MESSAGEID); + SOAPElement messageID = it.hasNext() ? it.next() : null; + if (messageID != null) { + String idValue = messageID.getTextContent(); + // Store the value of the message ID element into the message under "WS_MESSAGE_ID"... + msg.getHeaders().put(WS_MESSAGE_ID, idValue); + } // end if + } // end method handleMessageID + // Special WS_Addressing values + private static String WS_ADDR_ANONYMOUS = "http://www.w3.org/2005/08/addressing/anonymous"; + private static String WS_ADDR_NONE = "http://www.w3.org/2005/08/addressing/none"; + + /** + * Check if the received callback address has either of the special WS-Addressing forms which are outlawed by the + * Web Service Binding specification [BWS50004] + * @param callbackAddress - the received callback address + * @param inMC - the Axis message context for the received forward call + * @throws AxisFault - throws a "OnlyNonAnonymousAddressSupportedFault" if the callback address has either of the special forms + */ + private void checkCallbackAddress( String callbackAddress, SOAPMessage request) { + // If the address is anonymous or none, throw a SOAP fault... + if( WS_ADDR_ANONYMOUS.equals(callbackAddress) || WS_ADDR_NONE.equals(callbackAddress) ) { + triggerOnlyNonAnonymousAddressSupportedFault(request, "wsa:From"); + } + } // end method checkCallbackAddress + // wsa:OnlyAnonymousAddressSupported + + // wsa:OnlyNonAnonymousAddressSupported + public void triggerOnlyNonAnonymousAddressSupportedFault(SOAPMessage request, String incorrectHeaderName){ +// TODO +// String namespace = (String)messageContext.getProperty(AddressingConstants.WS_ADDRESSING_VERSION); +// if (Submission.WSA_NAMESPACE.equals(namespace)) { +// triggerAddressingFault(messageContext, Final.FAULT_HEADER_PROB_HEADER_QNAME, +// AddressingConstants.WSA_DEFAULT_PREFIX + ":" + +// incorrectHeaderName, Submission.FAULT_INVALID_HEADER, +// null, AddressingMessages.getMessage( +// "spec.submission.FAULT_INVALID_HEADER_REASON")); +// } else { +// triggerAddressingFault(messageContext, Final.FAULT_HEADER_PROB_HEADER_QNAME, +// AddressingConstants.WSA_DEFAULT_PREFIX + ":" + +// incorrectHeaderName, Final.FAULT_INVALID_HEADER, +// Final.FAULT_ONLY_NON_ANONYMOUS_ADDRESS_SUPPORTED, +// AddressingMessages.getMessage( +// "spec.final.FAULT_INVALID_HEADER_REASON")); +// } + } } |