Author: eglynn Date: Thu Jul 5 10:05:16 2007 New Revision: 553561 URL: http://svn.apache.org/viewvc?view=rev&rev=553561 Log: Added support for <wsaw:Action> extension attribute on <wsdl:input> messages, and for allowing the presence of the <wsaw:UsingAddressing> extension element to be considered purely advisory (i.e. so that its absence doesn't prevent the encoding of WS-A headers).
Modified: incubator/cxf/trunk/api/src/main/java/org/apache/cxf/service/model/BindingMessageInfo.java incubator/cxf/trunk/rt/ws/addr/src/main/java/org/apache/cxf/ws/addressing/ContextUtils.java incubator/cxf/trunk/rt/ws/addr/src/main/java/org/apache/cxf/ws/addressing/MAPAggregator.java incubator/cxf/trunk/rt/ws/addr/src/main/java/org/apache/cxf/ws/addressing/WSAddressingFeature.java incubator/cxf/trunk/rt/ws/addr/src/test/java/org/apache/cxf/ws/addressing/MAPAggregatorTest.java Modified: incubator/cxf/trunk/api/src/main/java/org/apache/cxf/service/model/BindingMessageInfo.java URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/api/src/main/java/org/apache/cxf/service/model/BindingMessageInfo.java?view=diff&rev=553561&r1=553560&r2=553561 ============================================================================== --- incubator/cxf/trunk/api/src/main/java/org/apache/cxf/service/model/BindingMessageInfo.java (original) +++ incubator/cxf/trunk/api/src/main/java/org/apache/cxf/service/model/BindingMessageInfo.java Thu Jul 5 10:05:16 2007 @@ -27,7 +27,9 @@ BindingOperationInfo op; private List<MessagePartInfo> messageParts; - + public BindingMessageInfo() { + } + protected BindingMessageInfo(MessageInfo m, BindingOperationInfo boi) { op = boi; msg = m; Modified: incubator/cxf/trunk/rt/ws/addr/src/main/java/org/apache/cxf/ws/addressing/ContextUtils.java URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/ws/addr/src/main/java/org/apache/cxf/ws/addressing/ContextUtils.java?view=diff&rev=553561&r1=553560&r2=553561 ============================================================================== --- incubator/cxf/trunk/rt/ws/addr/src/main/java/org/apache/cxf/ws/addressing/ContextUtils.java (original) +++ incubator/cxf/trunk/rt/ws/addr/src/main/java/org/apache/cxf/ws/addressing/ContextUtils.java Thu Jul 5 10:05:16 2007 @@ -21,6 +21,7 @@ import java.lang.reflect.Method; +import java.util.Map; import java.util.UUID; import java.util.concurrent.Executor; import java.util.logging.Level; @@ -31,6 +32,7 @@ import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBException; +import javax.xml.namespace.QName; import javax.xml.ws.RequestWrapper; import javax.xml.ws.ResponseWrapper; import javax.xml.ws.WebFault; @@ -39,6 +41,7 @@ import org.apache.cxf.binding.soap.model.SoapOperationInfo; import org.apache.cxf.common.logging.LogUtils; import org.apache.cxf.common.util.PackageUtils; +import org.apache.cxf.common.util.TwoStageMap; import org.apache.cxf.endpoint.ConduitSelector; import org.apache.cxf.endpoint.Endpoint; import org.apache.cxf.endpoint.NullConduitSelector; @@ -49,6 +52,7 @@ import org.apache.cxf.message.Exchange; import org.apache.cxf.message.Message; import org.apache.cxf.service.model.BindingOperationInfo; +import org.apache.cxf.service.model.MessageInfo; import org.apache.cxf.service.model.OperationInfo; import org.apache.cxf.transport.Conduit; import org.apache.cxf.transport.Destination; @@ -78,6 +82,10 @@ PackageUtils.getPackageName(EndpointReferenceType.class); private static final EndpointReferenceType NONE_ENDPOINT_REFERENCE = EndpointReferenceUtils.getEndpointReference(Names.WSA_NONE_ADDRESS); + private static final String HTTP_URI_SCHEME = "http:"; + private static final String URI_AUTHORITY_PREFIX = "//"; + private static final Map<BindingOperationInfo, String> ACTION_MAP = + new TwoStageMap<BindingOperationInfo, String>(); private static final Logger LOG = LogUtils.getL7dLogger(ContextUtils.class); @@ -635,78 +643,183 @@ */ public static AttributedURIType getAction(Message message) { String action = null; - // REVISIT: add support for @{Fault}Action annotation (generated - // from the wsaw:Action WSDL element) LOG.fine("Determining action"); Exception fault = message.getContent(Exception.class); - if (null == fault) { + + // REVISIT: add support for @{Fault}Action annotation (generated + // from the wsaw:Action WSDL element). For the moment we just + // pick up the wsaw:Action attribute by walking the WSDL model + // directly + action = getActionFromServiceModel(message, fault); + + if (action == null) { + Method method = getMethod(message); + LOG.fine("method: " + method + ", fault: " + fault); + if (method != null) { + action = getActionFromAnnotations(message, method, fault); + } + } + LOG.fine("action: " + action); + return action != null ? getAttributedURI(action) : null; + } + + /** + * Get action from service model. + * + * @param message the current message + * @param fault the fault if one is set + */ + private static String getActionFromServiceModel(Message message, + Exception fault) { + String action = null; + if (fault == null) { BindingOperationInfo bindingOpInfo = message.getExchange().get(BindingOperationInfo.class); if (bindingOpInfo != null) { - SoapOperationInfo soi = bindingOpInfo.getExtensor(SoapOperationInfo.class); + SoapOperationInfo soi = + bindingOpInfo.getExtensor(SoapOperationInfo.class); if (null != soi) { action = soi.getAction(); } + + if (action == null || "".equals(action)) { + String cachedAction = ACTION_MAP.get(bindingOpInfo); + if (cachedAction == null) { + MessageInfo msgInfo = + ContextUtils.isRequestor(message) + ? bindingOpInfo.getInput().getMessageInfo() + : bindingOpInfo.getOutput().getMessageInfo(); + action = getActionFromMessageAttributes(bindingOpInfo, + msgInfo); + } else { + action = cachedAction; + } + } } + } else { + // FaultAction attribute is not defined in + // http://www.w3.org/2005/02/addressing/wsdl schema } - Method method = null; - if (null == action) { - method = getMethod(message); + LOG.fine("action determined from service model: " + action); + return action; + } + + /** + * Get action from attributes on MessageInfo + * + * @param bindingOpInfo the current BindingOperationInfo + * @param msgInfo the current MessageInfo + * @return the action if set + */ + private static String getActionFromMessageAttributes( + BindingOperationInfo bindingOpInfo, + MessageInfo msgInfo) { + String action = null; + if (msgInfo != null + && msgInfo.getExtensionAttributes() != null) { + QName attr = (QName) + msgInfo.getExtensionAttributes().get(Names.WSAW_ACTION_QNAME); + if (attr != null) { + action = getURI(attr.getLocalPart()); + ACTION_MAP.put(bindingOpInfo, action); + } } - LOG.fine("method: " + method + ", fault: " + fault); - if (method != null) { - if (fault != null) { - WebFault webFault = fault.getClass().getAnnotation(WebFault.class); - if (webFault != null) { - action = getAction(webFault.targetNamespace(), - method, - webFault.name(), - true); - } + return action; + } + + /** + * Get action from annotations. + * + * @param message the current message + * @param method the invoked on method + * @param fault the fault if one is set + */ + private static String getActionFromAnnotations(Message message, + Method method, + Exception fault) { + String action = null; + if (fault != null) { + WebFault webFault = fault.getClass().getAnnotation(WebFault.class); + if (webFault != null) { + action = getAction(webFault.targetNamespace(), + method, + webFault.name(), + true); + } + } else { + String namespace = getWrapperNamespace(message, method); + if (namespace != null) { + action = getAction(namespace, + method, + getWrapperLocalName(message, method), + false); } else { - if (ContextUtils.isRequestor(message)) { - RequestWrapper requestWrapper = - method.getAnnotation(RequestWrapper.class); - if (requestWrapper != null) { - action = getAction(requestWrapper.targetNamespace(), - method, - requestWrapper.localName(), - false); - } else { - WebService wsAnnotation = method.getDeclaringClass().getAnnotation(WebService.class); - WebMethod wmAnnotation = method.getAnnotation(WebMethod.class); - - action = getAction(wsAnnotation.targetNamespace(), - method, - wmAnnotation.operationName(), - false); - } - - } else { - ResponseWrapper responseWrapper = - method.getAnnotation(ResponseWrapper.class); - if (responseWrapper != null) { - action = getAction(responseWrapper.targetNamespace(), - method, - responseWrapper.localName(), - false); - } else { - //RPC-Literal case. - WebService wsAnnotation = method.getDeclaringClass().getAnnotation(WebService.class); - WebMethod wmAnnotation = method.getAnnotation(WebMethod.class); - - if (wsAnnotation != null && wmAnnotation != null) { - action = getAction(wsAnnotation.targetNamespace(), - method, - wmAnnotation.operationName(), - false); - } - } - } + WebService wsAnnotation = + method.getDeclaringClass().getAnnotation(WebService.class); + WebMethod wmAnnotation = + method.getAnnotation(WebMethod.class); + action = wsAnnotation != null && wmAnnotation != null + ? getAction(wsAnnotation.targetNamespace(), + method, + wmAnnotation.operationName(), + false) + : null; } } - LOG.fine("action: " + action); - return action != null ? getAttributedURI(action) : null; + LOG.fine("action determined from annotations: " + action); + return action; + } + + /** + * Get the target namespace from the {Request|Response}Wrapper annotation + * + * @param message the current message + * @param method the target method + * @return the annotated namespace + */ + private static String getWrapperNamespace(Message message, + Method method) { + String namespace = null; + if (ContextUtils.isRequestor(message)) { + RequestWrapper requestWrapper = + method.getAnnotation(RequestWrapper.class); + if (requestWrapper != null) { + namespace = requestWrapper.targetNamespace(); + } + } else { + ResponseWrapper responseWrapper = + method.getAnnotation(ResponseWrapper.class); + if (responseWrapper != null) { + namespace = responseWrapper.targetNamespace(); + } + } + return namespace; + } + + /** + * Get the target local name from the {Request|Response}Wrapper annotation + * + * @param message the current message + * @param method the target method + * @return the annotated local name + */ + private static String getWrapperLocalName(Message message, + Method method) { + String localName = null; + if (ContextUtils.isRequestor(message)) { + RequestWrapper requestWrapper = + method.getAnnotation(RequestWrapper.class); + if (requestWrapper != null) { + localName = requestWrapper.localName(); + } + } else { + ResponseWrapper responseWrapper = + method.getAnnotation(ResponseWrapper.class); + if (responseWrapper != null) { + localName = responseWrapper.localName(); + } + } + return localName; } /** @@ -752,6 +865,22 @@ } } return method; + } + + /** + * @param s a string that may be a URI without a scheme identifier + * @return a properly formed URI + */ + private static String getURI(String s) { + String uri = null; + if (s.startsWith(HTTP_URI_SCHEME)) { + uri = s; + } else if (s.startsWith(URI_AUTHORITY_PREFIX)) { + uri = HTTP_URI_SCHEME + s; + } else { + uri = HTTP_URI_SCHEME + URI_AUTHORITY_PREFIX + s; + } + return uri; } public static EndpointReferenceType getNoneEndpointReference() { Modified: incubator/cxf/trunk/rt/ws/addr/src/main/java/org/apache/cxf/ws/addressing/MAPAggregator.java URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/ws/addr/src/main/java/org/apache/cxf/ws/addressing/MAPAggregator.java?view=diff&rev=553561&r1=553560&r2=553561 ============================================================================== --- incubator/cxf/trunk/rt/ws/addr/src/main/java/org/apache/cxf/ws/addressing/MAPAggregator.java (original) +++ incubator/cxf/trunk/rt/ws/addr/src/main/java/org/apache/cxf/ws/addressing/MAPAggregator.java Thu Jul 5 10:05:16 2007 @@ -71,7 +71,8 @@ */ private Map<Endpoint, Boolean> usingAddressing = new ConcurrentHashMap<Endpoint, Boolean>(); - + private boolean usingAddressingAdvisory; + private boolean allowDuplicates = true; /** @@ -97,6 +98,29 @@ allowDuplicates = ad; } + /** + * Whether the presence of the <wsaw:UsingAddressing> element + * in the WSDL is purely advisory, i.e. its absence doesn't prevent + * the encoding of WS-A headers. + * + * @return true if the presence of the <wsaw:UsingAddressing> element is + * advisory + */ + public boolean isUsingAddressingAdvisory() { + return usingAddressingAdvisory; + } + + /** + * Controls whether the presence of the <wsaw:UsingAddressing> element + * in the WSDL is purely advisory, i.e. its absence doesn't prevent + * the encoding of WS-A headers. + * + * @param advisory true if the presence of the <wsaw:UsingAddressing> + * element is to be advisory + */ + public void setUsingAddressingAdvisory(boolean advisory) { + usingAddressingAdvisory = advisory; + } /** * Invoked for normal processing of inbound and outbound messages. @@ -124,7 +148,8 @@ private boolean usingAddressing(Message message) { boolean ret = false; if (ContextUtils.isRequestor(message)) { - ret = WSAContextUtils.retrieveUsingAddressing(message) + ret = usingAddressingAdvisory + || WSAContextUtils.retrieveUsingAddressing(message) || hasUsingAddressing(message) || hasAddressingAssertion(message); } else { Modified: incubator/cxf/trunk/rt/ws/addr/src/main/java/org/apache/cxf/ws/addressing/WSAddressingFeature.java URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/ws/addr/src/main/java/org/apache/cxf/ws/addressing/WSAddressingFeature.java?view=diff&rev=553561&r1=553560&r2=553561 ============================================================================== --- incubator/cxf/trunk/rt/ws/addr/src/main/java/org/apache/cxf/ws/addressing/WSAddressingFeature.java (original) +++ incubator/cxf/trunk/rt/ws/addr/src/main/java/org/apache/cxf/ws/addressing/WSAddressingFeature.java Thu Jul 5 10:05:16 2007 @@ -50,4 +50,12 @@ public boolean isAllowDuplicates() { return mapAggregator.allowDuplicates(); } + + public void setUsingAddressingAdvisory(boolean advisory) { + mapAggregator.setUsingAddressingAdvisory(advisory); + } + + public boolean isUsingAddressingAdvisory() { + return mapAggregator.isUsingAddressingAdvisory(); + } } Modified: incubator/cxf/trunk/rt/ws/addr/src/test/java/org/apache/cxf/ws/addressing/MAPAggregatorTest.java URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/ws/addr/src/test/java/org/apache/cxf/ws/addressing/MAPAggregatorTest.java?view=diff&rev=553561&r1=553560&r2=553561 ============================================================================== --- incubator/cxf/trunk/rt/ws/addr/src/test/java/org/apache/cxf/ws/addressing/MAPAggregatorTest.java (original) +++ incubator/cxf/trunk/rt/ws/addr/src/test/java/org/apache/cxf/ws/addressing/MAPAggregatorTest.java Thu Jul 5 10:05:16 2007 @@ -37,6 +37,7 @@ import org.apache.cxf.message.Message; import org.apache.cxf.message.MessageImpl; import org.apache.cxf.service.model.BindingInfo; +import org.apache.cxf.service.model.BindingMessageInfo; import org.apache.cxf.service.model.BindingOperationInfo; import org.apache.cxf.service.model.EndpointInfo; import org.apache.cxf.service.model.OperationInfo; @@ -758,9 +759,20 @@ String op(); } + private static class TestBindingMessageInfo extends BindingMessageInfo { + } + private static class TestBindingOperationInfo extends BindingOperationInfo { public TestBindingOperationInfo(OperationInfo oi) { opInfo = oi; + } + + public BindingMessageInfo getInput() { + return new TestBindingMessageInfo(); + } + + public BindingMessageInfo getOutput() { + return new TestBindingMessageInfo(); } } }