From 249a5a8309cdd09130d6dac06f6463d28237fbcc Mon Sep 17 00:00:00 2001 From: Arjen Poutsma Date: Sat, 23 Feb 2008 18:30:51 +0000 Subject: [PATCH] - Split out WS-Addressing to multiple packages (SWS-84) - Javadoc --- ...AnnotationActionMethodEndpointMapping.java | 94 ------------ .../ws/soap/addressing/annotation/Action.java | 6 - .../soap/addressing/annotation/Address.java | 5 +- .../AnnotationActionEndpointMapping.java | 142 ++++++++++++++++++ ...tationActionMethodEndpointMappingTest.java | 36 ++++- .../ws/soap/addressing/server/valid.xml | 17 +++ 6 files changed, 188 insertions(+), 112 deletions(-) delete mode 100644 core-tiger/src/main/java/org/springframework/ws/soap/addressing/AnnotationActionMethodEndpointMapping.java create mode 100644 core-tiger/src/main/java/org/springframework/ws/soap/addressing/server/AnnotationActionEndpointMapping.java rename core-tiger/src/test/java/org/springframework/ws/soap/addressing/{ => server}/AnnotationActionMethodEndpointMappingTest.java (70%) create mode 100644 core-tiger/src/test/resources/org/springframework/ws/soap/addressing/server/valid.xml diff --git a/core-tiger/src/main/java/org/springframework/ws/soap/addressing/AnnotationActionMethodEndpointMapping.java b/core-tiger/src/main/java/org/springframework/ws/soap/addressing/AnnotationActionMethodEndpointMapping.java deleted file mode 100644 index 3252d0a2..00000000 --- a/core-tiger/src/main/java/org/springframework/ws/soap/addressing/AnnotationActionMethodEndpointMapping.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2008 the original author or authors. - * - * Licensed 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.springframework.ws.soap.addressing; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Method; -import java.net.URI; -import java.net.URISyntaxException; - -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.config.BeanPostProcessor; -import org.springframework.core.annotation.AnnotationUtils; -import org.springframework.util.StringUtils; -import org.springframework.ws.server.endpoint.MethodEndpoint; -import org.springframework.ws.server.endpoint.annotation.Endpoint; -import org.springframework.ws.soap.addressing.annotation.Action; -import org.springframework.ws.soap.addressing.annotation.Address; - -/** - * @author Arjen Poutsma - * @since 1.5.0 - */ -public class AnnotationActionMethodEndpointMapping extends AbstractActionMethodEndpointMapping - implements BeanPostProcessor { - - /** Returns the 'endpoint' annotation type. Default is {@link Endpoint}. */ - protected Class getEndpointAnnotationType() { - return Endpoint.class; - } - - public final Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { - return bean; - } - - public final Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { - if (getEndpointClass(bean).getAnnotation(getEndpointAnnotationType()) != null) { - registerMethods(bean); - } - return bean; - } - - protected URI getActionForMethod(Method method) { - Action action = method.getAnnotation(Action.class); - if (action != null) { - try { - return new URI(action.value()); - } - catch (URISyntaxException e) { - // ignore - } - } - return null; - } - - protected Object getEndpointInternal(URI to, URI action) { - MethodEndpoint methodEndpoint = (MethodEndpoint) lookupEndpoint(action); - if (methodEndpoint != null) { - // respect the Address annotation, if set - Class endpointClass = methodEndpoint.getMethod().getDeclaringClass(); - Address address = AnnotationUtils.findAnnotation(endpointClass, Address.class); - if (address != null && StringUtils.hasText(address.value())) { - try { - URI addressUri = new URI(address.value()); - if (to.equals(addressUri)) { - return methodEndpoint; - } - } - catch (URISyntaxException e) { - throw new IllegalArgumentException( - "Invalid Address annotation [" + address.value() + "] on [" + endpointClass + "]"); - } - } - else { - // address not set - return methodEndpoint; - } - } - return null; - } -} diff --git a/core-tiger/src/main/java/org/springframework/ws/soap/addressing/annotation/Action.java b/core-tiger/src/main/java/org/springframework/ws/soap/addressing/annotation/Action.java index 9a8bace3..fcaf936b 100644 --- a/core-tiger/src/main/java/org/springframework/ws/soap/addressing/annotation/Action.java +++ b/core-tiger/src/main/java/org/springframework/ws/soap/addressing/annotation/Action.java @@ -37,10 +37,4 @@ public @interface Action { /** Signifies the value for the request WS-Addressing Action header that is handled by the method. */ String value(); - /** - * Explicit value of the WS-Addressing Action message addressing property for the output - * message of the operation. - */ - String output() default ""; - } diff --git a/core-tiger/src/main/java/org/springframework/ws/soap/addressing/annotation/Address.java b/core-tiger/src/main/java/org/springframework/ws/soap/addressing/annotation/Address.java index 63adfe5c..e32f16df 100644 --- a/core-tiger/src/main/java/org/springframework/ws/soap/addressing/annotation/Address.java +++ b/core-tiger/src/main/java/org/springframework/ws/soap/addressing/annotation/Address.java @@ -24,11 +24,8 @@ import java.lang.annotation.Target; /** * Marks an endpoint with a WS-Addressing Address. If this annotation is applied, the {@link #value()} is - * compared to the {@link org.springframework.ws.soap.addressing.MessageAddressingProperties#getTo() destination} + * compared to the {@link org.springframework.ws.soap.addressing.core.MessageAddressingProperties#getTo() destination} * property of the incominging message. - *

- * as the handler for an incoming request. The annotation value signifies the value for the request WS-Addressing - * Action header that is handled by the method. * * @author Arjen Poutsma * @since 1.5.0 diff --git a/core-tiger/src/main/java/org/springframework/ws/soap/addressing/server/AnnotationActionEndpointMapping.java b/core-tiger/src/main/java/org/springframework/ws/soap/addressing/server/AnnotationActionEndpointMapping.java new file mode 100644 index 00000000..60e7a2ba --- /dev/null +++ b/core-tiger/src/main/java/org/springframework/ws/soap/addressing/server/AnnotationActionEndpointMapping.java @@ -0,0 +1,142 @@ +/* + * Copyright 2008 the original author or authors. + * + * Licensed 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.springframework.ws.soap.addressing.server; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.net.URI; +import java.net.URISyntaxException; + +import org.springframework.aop.support.AopUtils; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.core.JdkVersion; +import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; +import org.springframework.ws.server.endpoint.MethodEndpoint; +import org.springframework.ws.server.endpoint.annotation.Endpoint; +import org.springframework.ws.soap.addressing.annotation.Action; +import org.springframework.ws.soap.addressing.annotation.Address; + +/** + * Implementation of the {@link org.springframework.ws.server.EndpointMapping} interface that uses the {@link Action} + * annotation to map methods to a WS-Addressing Action header. + *

+ * Endpoints typically have the following form: + *

+ * @Endpoint
+ * @Address("mailto:joe@fabrikam123.example")
+ * public class MyEndpoint{
+ *    @Action("http://fabrikam123.example/mail/Delete")
+ *    public Source doSomethingWithRequest() {
+ *       ...
+ *    }
+ * }
+ * 
+ *

+ * If set, the {@link @Address} annotation on the endpoint class should be equal to the {@link + * org.springframework.ws.soap.addressing.core.MessageAddressingProperties#getTo() destination} property of the + * incominging message. + * + * @author Arjen Poutsma + * @see Action + * @see Address + * @since 1.5.0 + */ +public class AnnotationActionEndpointMapping extends AbstractActionEndpointMapping implements BeanPostProcessor { + + /** Returns the 'endpoint' annotation type. Default is {@link Endpoint}. */ + protected Class getEndpointAnnotationType() { + return Endpoint.class; + } + + public final Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { + return bean; + } + + public final Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { + if (AopUtils.getTargetClass(bean).getAnnotation(getEndpointAnnotationType()) != null) { + registerMethods(bean); + } + return bean; + } + + /** + * Helper method that registers the methods of the given bean. This method iterates over the methods of the bean, + * and calls {@link #getActionForMethod(java.lang.reflect.Method)} for each. If this returns a URI, the method is + * registered using {@link #registerEndpoint(java.net.URI, Object)}. + * + * @see #getActionForMethod (java.lang.reflect.Method) + */ + protected void registerMethods(Object endpoint) { + Assert.notNull(endpoint, "'endpoint' must not be null"); + Method[] methods = AopUtils.getTargetClass(endpoint).getMethods(); + for (int i = 0; i < methods.length; i++) { + if (JdkVersion.isAtLeastJava15() && methods[i].isSynthetic() || + methods[i].getDeclaringClass().equals(Object.class)) { + continue; + } + URI action = getActionForMethod(methods[i]); + if (action != null) { + registerEndpoint(action, new MethodEndpoint(endpoint, methods[i])); + } + } + } + + /** + * Returns the action value for the specified method. Default implementation looks for the {@link Action} annotation + * value. + */ + protected URI getActionForMethod(Method method) { + Action action = method.getAnnotation(Action.class); + if (action != null && StringUtils.hasText(action.value())) { + try { + return new URI(action.value()); + } + catch (URISyntaxException e) { + // ignore + } + } + return null; + } + + /** + * Returns the address property of the given {@link MethodEndpoint}, by looking for the {@link Address} annotation. + * The value of this property should match the {@link org.springframework.ws.soap.addressing.core.MessageAddressingProperties#getTo() + * destination} of incoming messages. Returns null if the anotation is not present, thus ignoring the + * destination property. + * + * @param endpoint the method endpoint to return the address for + * @return the endpoint address; or null to ignore the destination property + */ + protected URI getEndpointAddress(Object endpoint) { + MethodEndpoint methodEndpoint = (MethodEndpoint) endpoint; + Class endpointClass = methodEndpoint.getMethod().getDeclaringClass(); + Address address = AnnotationUtils.findAnnotation(endpointClass, Address.class); + if (address != null && StringUtils.hasText(address.value())) { + try { + return new URI(address.value()); + } + catch (URISyntaxException e) { + throw new IllegalArgumentException( + "Invalid Address annotation [" + address.value() + "] on [" + endpointClass + "]"); + } + } + return null; + } +} diff --git a/core-tiger/src/test/java/org/springframework/ws/soap/addressing/AnnotationActionMethodEndpointMappingTest.java b/core-tiger/src/test/java/org/springframework/ws/soap/addressing/server/AnnotationActionMethodEndpointMappingTest.java similarity index 70% rename from core-tiger/src/test/java/org/springframework/ws/soap/addressing/AnnotationActionMethodEndpointMappingTest.java rename to core-tiger/src/test/java/org/springframework/ws/soap/addressing/server/AnnotationActionMethodEndpointMappingTest.java index 97c8c7a9..f6c089d8 100644 --- a/core-tiger/src/test/java/org/springframework/ws/soap/addressing/AnnotationActionMethodEndpointMappingTest.java +++ b/core-tiger/src/test/java/org/springframework/ws/soap/addressing/server/AnnotationActionMethodEndpointMappingTest.java @@ -14,11 +14,18 @@ * limitations under the License. */ -package org.springframework.ws.soap.addressing; +package org.springframework.ws.soap.addressing.server; import java.io.IOException; +import java.io.InputStream; +import javax.xml.soap.MessageFactory; +import javax.xml.soap.MimeHeaders; +import javax.xml.soap.SOAPConstants; import javax.xml.soap.SOAPException; +import org.custommonkey.xmlunit.XMLTestCase; +import org.custommonkey.xmlunit.XMLUnit; + import org.springframework.context.support.StaticApplicationContext; import org.springframework.ws.context.DefaultMessageContext; import org.springframework.ws.context.MessageContext; @@ -30,16 +37,20 @@ import org.springframework.ws.soap.addressing.annotation.Address; import org.springframework.ws.soap.saaj.SaajSoapMessage; import org.springframework.ws.soap.saaj.SaajSoapMessageFactory; -public class AnnotationActionMethodEndpointMappingTest extends AbstractWsAddressingTestCase { +public class AnnotationActionMethodEndpointMappingTest extends XMLTestCase { private StaticApplicationContext applicationContext; - private AnnotationActionMethodEndpointMapping mapping; + private AnnotationActionEndpointMapping mapping; - protected void onSetUp() throws Exception { + private MessageFactory messageFactory; + + protected void setUp() throws Exception { + messageFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL); + XMLUnit.setIgnoreWhitespace(true); applicationContext = new StaticApplicationContext(); - applicationContext.registerSingleton("mapping", AnnotationActionMethodEndpointMapping.class); - mapping = (AnnotationActionMethodEndpointMapping) applicationContext.getBean("mapping"); + applicationContext.registerSingleton("mapping", AnnotationActionEndpointMapping.class); + mapping = (AnnotationActionEndpointMapping) applicationContext.getBean("mapping"); } public void testNoAddress() throws Exception { @@ -65,8 +76,17 @@ public class AnnotationActionMethodEndpointMappingTest extends AbstractWsAddress } private MessageContext createMessageContext() throws SOAPException, IOException { - SaajSoapMessage message = loadSaajMessage("200408/valid.xml"); - return new DefaultMessageContext(message, new SaajSoapMessageFactory(messageFactory)); + MimeHeaders mimeHeaders = new MimeHeaders(); + mimeHeaders.addHeader("Content-Type", " application/soap+xml"); + InputStream is = getClass().getResourceAsStream("valid.xml"); + assertNotNull("Could not load valid.xml", is); + try { + SaajSoapMessage message = new SaajSoapMessage(messageFactory.createMessage(mimeHeaders, is)); + return new DefaultMessageContext(message, new SaajSoapMessageFactory(messageFactory)); + } + finally { + is.close(); + } } @Endpoint diff --git a/core-tiger/src/test/resources/org/springframework/ws/soap/addressing/server/valid.xml b/core-tiger/src/test/resources/org/springframework/ws/soap/addressing/server/valid.xml new file mode 100644 index 00000000..405b87ef --- /dev/null +++ b/core-tiger/src/test/resources/org/springframework/ws/soap/addressing/server/valid.xml @@ -0,0 +1,17 @@ + + + uuid:aaaabbbb-cccc-dddd-eeee-ffffffffffff + + http://example.com/business/client1 + + mailto:joe@fabrikam123.example + http://fabrikam123.example/mail/Delete + + + + 42 + + +