diff --git a/core-tiger/pom.xml b/core-tiger/pom.xml new file mode 100644 index 000000000..56ab0e1e5 --- /dev/null +++ b/core-tiger/pom.xml @@ -0,0 +1,30 @@ + + + + spring-ws + org.springframework.ws + 1.0-m4-SNAPSHOT + + 4.0.0 + spring-ws-core-tiger + Spring WS Core - Java 5 + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.5 + 1.5 + + + + + + + + org.springframework.ws + spring-ws-core + + + \ No newline at end of file diff --git a/sandbox/src/main/java/org/springframework/ws/server/endpoint/adapter/XPathParamAnnotationEndpointAdapter.java b/core-tiger/src/main/java/org/springframework/ws/server/endpoint/adapter/XPathParamAnnotationEndpointAdapter.java similarity index 89% rename from sandbox/src/main/java/org/springframework/ws/server/endpoint/adapter/XPathParamAnnotationEndpointAdapter.java rename to core-tiger/src/main/java/org/springframework/ws/server/endpoint/adapter/XPathParamAnnotationEndpointAdapter.java index 707ba938a..028ecce07 100644 --- a/sandbox/src/main/java/org/springframework/ws/server/endpoint/adapter/XPathParamAnnotationEndpointAdapter.java +++ b/core-tiger/src/main/java/org/springframework/ws/server/endpoint/adapter/XPathParamAnnotationEndpointAdapter.java @@ -23,9 +23,6 @@ import javax.xml.namespace.QName; import javax.xml.transform.Source; import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerException; -import javax.xml.transform.dom.DOMResult; -import javax.xml.transform.dom.DOMSource; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpressionException; @@ -36,6 +33,7 @@ import org.springframework.ws.context.MessageContext; import org.springframework.ws.server.endpoint.MethodEndpoint; import org.springframework.ws.server.endpoint.annotation.XPathParam; +import org.springframework.xml.dom.DomUtils; import org.springframework.xml.namespace.SimpleNamespaceContext; import org.w3c.dom.Element; import org.w3c.dom.Node; @@ -106,7 +104,8 @@ private boolean isSuportedType(Class clazz) { protected void invokeInternal(MessageContext messageContext, MethodEndpoint methodEndpoint) throws Exception { try { - Element payloadElement = getMessagePayloadElement(messageContext.getRequest()); + Element payloadElement = + DomUtils.getRootElement(messageContext.getRequest().getPayloadSource(), getTransformerFactory()); Object[] args = getMethodArguments(payloadElement, methodEndpoint.getMethod()); Object result = methodEndpoint.invoke(args); if (result != null && result instanceof Source) { @@ -126,19 +125,6 @@ protected void invokeInternal(MessageContext messageContext, MethodEndpoint meth } } - private Element getMessagePayloadElement(WebServiceMessage message) throws TransformerException { - if (message.getPayloadSource() instanceof DOMSource) { - DOMSource domSource = (DOMSource) message.getPayloadSource(); - if (domSource.getNode().getNodeType() == Node.ELEMENT_NODE) { - return (Element) domSource.getNode(); - } - } - Transformer transformer = createTransformer(); - DOMResult domResult = new DOMResult(); - transformer.transform(message.getPayloadSource(), domResult); - return (Element) domResult.getNode().getFirstChild(); - } - private Object[] getMethodArguments(Element payloadElement, Method method) throws XPathExpressionException { Class[] parameterTypes = method.getParameterTypes(); XPath xpath = createXPath(); diff --git a/sandbox/src/main/java/org/springframework/ws/server/endpoint/annotation/Endpoint.java b/core-tiger/src/main/java/org/springframework/ws/server/endpoint/annotation/Endpoint.java similarity index 86% rename from sandbox/src/main/java/org/springframework/ws/server/endpoint/annotation/Endpoint.java rename to core-tiger/src/main/java/org/springframework/ws/server/endpoint/annotation/Endpoint.java index 9aecfbd11..ae1d27d1d 100644 --- a/sandbox/src/main/java/org/springframework/ws/server/endpoint/annotation/Endpoint.java +++ b/core-tiger/src/main/java/org/springframework/ws/server/endpoint/annotation/Endpoint.java @@ -22,14 +22,14 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.springframework.ws.server.endpoint.mapping.AbstractAnnotationEndpointMapping; -import org.springframework.ws.soap.server.endpoint.mapping.SoapActionAnnotationEndpointMapping; +import org.springframework.ws.server.endpoint.mapping.AbstractAnnotationMethodEndpointMapping; +import org.springframework.ws.soap.server.endpoint.mapping.SoapActionAnnotationMethodEndpointMapping; /** * Marks a class as an endpoint. *

- * Instances of this class are typically picked up by an {@link AbstractAnnotationEndpointMapping} implementation, such - * as {@link SoapActionAnnotationEndpointMapping}. + * Instances of this class are typically picked up by an {@link AbstractAnnotationMethodEndpointMapping} implementation, + * such as {@link SoapActionAnnotationMethodEndpointMapping}. * * @author Arjen Poutsma */ diff --git a/sandbox/src/main/java/org/springframework/ws/server/endpoint/annotation/PayloadRootQName.java b/core-tiger/src/main/java/org/springframework/ws/server/endpoint/annotation/PayloadRoot.java similarity index 69% rename from sandbox/src/main/java/org/springframework/ws/server/endpoint/annotation/PayloadRootQName.java rename to core-tiger/src/main/java/org/springframework/ws/server/endpoint/annotation/PayloadRoot.java index e6c55b8d3..06bbef367 100644 --- a/sandbox/src/main/java/org/springframework/ws/server/endpoint/annotation/PayloadRootQName.java +++ b/core-tiger/src/main/java/org/springframework/ws/server/endpoint/annotation/PayloadRoot.java @@ -16,14 +16,23 @@ package org.springframework.ws.server.endpoint.annotation; +import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +/** + * Marks an endpoint method as the handler for an incoming request. The annotation value signifies the value for the + * request payload root element that is handled by the method. + * + * @author Arjen Poutsma + * @see org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping + */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) -public @interface PayloadRootQName { +@Documented +public @interface PayloadRoot { String value(); diff --git a/sandbox/src/main/java/org/springframework/ws/server/endpoint/annotation/XPathParam.java b/core-tiger/src/main/java/org/springframework/ws/server/endpoint/annotation/XPathParam.java similarity index 64% rename from sandbox/src/main/java/org/springframework/ws/server/endpoint/annotation/XPathParam.java rename to core-tiger/src/main/java/org/springframework/ws/server/endpoint/annotation/XPathParam.java index c5ba87172..c2acc9e4b 100644 --- a/sandbox/src/main/java/org/springframework/ws/server/endpoint/annotation/XPathParam.java +++ b/core-tiger/src/main/java/org/springframework/ws/server/endpoint/annotation/XPathParam.java @@ -21,15 +21,18 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -/** @author Arjen Poutsma */ +/** + * Indicates that a method parameter should be bound to an XPath expression. The annotation value signifies the XPath + * expression to use. The parameter can be of the following types:

+ * + * @author Arjen Poutsma + * @see org.springframework.ws.server.endpoint.adapter.XPathParamAnnotationEndpointAdapter + */ @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) public @interface XPathParam { - /** - * The XPathParam value. - * - * @return the - */ String value(); } diff --git a/sandbox/src/main/java/org/springframework/ws/server/endpoint/annotation/package.html b/core-tiger/src/main/java/org/springframework/ws/server/endpoint/annotation/package.html similarity index 100% rename from sandbox/src/main/java/org/springframework/ws/server/endpoint/annotation/package.html rename to core-tiger/src/main/java/org/springframework/ws/server/endpoint/annotation/package.html diff --git a/sandbox/src/main/java/org/springframework/ws/server/endpoint/mapping/AbstractAnnotationEndpointMapping.java b/core-tiger/src/main/java/org/springframework/ws/server/endpoint/mapping/AbstractAnnotationMethodEndpointMapping.java similarity index 83% rename from sandbox/src/main/java/org/springframework/ws/server/endpoint/mapping/AbstractAnnotationEndpointMapping.java rename to core-tiger/src/main/java/org/springframework/ws/server/endpoint/mapping/AbstractAnnotationMethodEndpointMapping.java index 54f2c3a8f..42321cfed 100644 --- a/sandbox/src/main/java/org/springframework/ws/server/endpoint/mapping/AbstractAnnotationEndpointMapping.java +++ b/core-tiger/src/main/java/org/springframework/ws/server/endpoint/mapping/AbstractAnnotationMethodEndpointMapping.java @@ -26,15 +26,17 @@ * Abstract base for {@link org.springframework.ws.server.EndpointMapping} implementations that map classes tagged with * an annotation. By default the annotation is {@link Endpoint}, but this can be overriden in subclasses. *

- * Each bean + * The methods of each bean carrying @Endpoint will be registered using {@link #registerMethods(Object)}. * * @author Arjen Poutsma */ -public abstract class AbstractAnnotationEndpointMapping extends AbstractMethodEndpointMapping +public abstract class AbstractAnnotationMethodEndpointMapping extends AbstractMethodEndpointMapping implements BeanPostProcessor { public final Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { - registerMethods(bean); + if (getEndpointClass(bean).getAnnotation(getEndpointAnnotationType()) != null) { + registerMethods(bean); + } return bean; } diff --git a/sandbox/src/main/java/org/springframework/ws/server/endpoint/mapping/PayloadRootQNameMethodEndpointMapping.java b/core-tiger/src/main/java/org/springframework/ws/server/endpoint/mapping/PayloadRootAnnotationMethodEndpointMapping.java similarity index 63% rename from sandbox/src/main/java/org/springframework/ws/server/endpoint/mapping/PayloadRootQNameMethodEndpointMapping.java rename to core-tiger/src/main/java/org/springframework/ws/server/endpoint/mapping/PayloadRootAnnotationMethodEndpointMapping.java index 02e096017..0383d970e 100644 --- a/sandbox/src/main/java/org/springframework/ws/server/endpoint/mapping/PayloadRootQNameMethodEndpointMapping.java +++ b/core-tiger/src/main/java/org/springframework/ws/server/endpoint/mapping/PayloadRootAnnotationMethodEndpointMapping.java @@ -18,20 +18,34 @@ import java.lang.reflect.Method; import javax.xml.namespace.QName; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; -import javax.xml.transform.dom.DOMResult; import org.springframework.core.annotation.AnnotationUtils; -import org.springframework.ws.WebServiceMessage; import org.springframework.ws.context.MessageContext; -import org.springframework.ws.server.endpoint.annotation.PayloadRootQName; +import org.springframework.ws.server.EndpointMapping; +import org.springframework.ws.server.endpoint.annotation.PayloadRoot; +import org.springframework.xml.dom.DomUtils; import org.springframework.xml.namespace.QNameUtils; import org.w3c.dom.Element; -/** @author Arjen Poutsma */ -public class PayloadRootQNameMethodEndpointMapping extends AbstractAnnotationEndpointMapping { +/** + * Implementation of the {@link EndpointMapping} interface that uses the {@link PayloadRoot} annotation to map methods + * to request payload root elements. + *

+ * Endpoints typically have the following form: + *

+ * @Endpoint
+ * public class MyEndpoint{
+ *    @Payload("{http://springframework.org/spring-ws}Request")
+ *    public Source doSomethingWithRequest() {
+ *       ...
+ *    }
+ * }
+ * 
+ * + * @author Arjen Poutsma + */ +public class PayloadRootAnnotationMethodEndpointMapping extends AbstractAnnotationMethodEndpointMapping { private static TransformerFactory transformerFactory; @@ -40,22 +54,15 @@ public class PayloadRootQNameMethodEndpointMapping extends AbstractAnnotationEnd } protected String getLookupKeyForMessage(MessageContext messageContext) throws Exception { - Element payloadElement = getMessagePayloadElement(messageContext.getRequest()); + Element payloadElement = + DomUtils.getRootElement(messageContext.getRequest().getPayloadSource(), transformerFactory); QName qName = QNameUtils.getQNameForNode(payloadElement); return qName != null ? qName.toString() : null; } protected String getLookupKeyForMethod(Method method) { - PayloadRootQName annotation = AnnotationUtils.getAnnotation(method, PayloadRootQName.class); + PayloadRoot annotation = AnnotationUtils.getAnnotation(method, PayloadRoot.class); return annotation != null ? annotation.value() : null; } - private Element getMessagePayloadElement(WebServiceMessage message) throws TransformerException { - Transformer transformer = transformerFactory.newTransformer(); - DOMResult domResult = new DOMResult(); - transformer.transform(message.getPayloadSource(), domResult); - return (Element) domResult.getNode().getFirstChild(); - } - - } diff --git a/sandbox/src/main/java/org/springframework/ws/soap/server/endpoint/annotation/SoapAction.java b/core-tiger/src/main/java/org/springframework/ws/soap/server/endpoint/annotation/SoapAction.java similarity index 72% rename from sandbox/src/main/java/org/springframework/ws/soap/server/endpoint/annotation/SoapAction.java rename to core-tiger/src/main/java/org/springframework/ws/soap/server/endpoint/annotation/SoapAction.java index 3857ce457..477e104f9 100644 --- a/sandbox/src/main/java/org/springframework/ws/soap/server/endpoint/annotation/SoapAction.java +++ b/core-tiger/src/main/java/org/springframework/ws/soap/server/endpoint/annotation/SoapAction.java @@ -16,14 +16,22 @@ package org.springframework.ws.soap.server.endpoint.annotation; +import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -/** @author Arjen Poutsma */ +/** + * Marks an endpoint method as the handler for an incoming request. The annotation value signifies the value for the + * request SOAPAction header that is handled by the method. + * + * @author Arjen Poutsma + * @see org.springframework.ws.soap.server.endpoint.mapping.SoapActionAnnotationMethodEndpointMapping + */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) +@Documented public @interface SoapAction { String value(); diff --git a/core-tiger/src/main/java/org/springframework/ws/soap/server/endpoint/annotation/package.html b/core-tiger/src/main/java/org/springframework/ws/soap/server/endpoint/annotation/package.html new file mode 100644 index 000000000..a6125b84d --- /dev/null +++ b/core-tiger/src/main/java/org/springframework/ws/soap/server/endpoint/annotation/package.html @@ -0,0 +1,5 @@ + + +JDK 1.5+ annotations for Spring-WS SOAP endpoints. + + diff --git a/sandbox/src/main/java/org/springframework/ws/soap/server/endpoint/mapping/SoapActionAnnotationEndpointMapping.java b/core-tiger/src/main/java/org/springframework/ws/soap/server/endpoint/mapping/SoapActionAnnotationMethodEndpointMapping.java similarity index 74% rename from sandbox/src/main/java/org/springframework/ws/soap/server/endpoint/mapping/SoapActionAnnotationEndpointMapping.java rename to core-tiger/src/main/java/org/springframework/ws/soap/server/endpoint/mapping/SoapActionAnnotationMethodEndpointMapping.java index 0fc27a535..e960070af 100644 --- a/sandbox/src/main/java/org/springframework/ws/soap/server/endpoint/mapping/SoapActionAnnotationEndpointMapping.java +++ b/core-tiger/src/main/java/org/springframework/ws/soap/server/endpoint/mapping/SoapActionAnnotationMethodEndpointMapping.java @@ -24,35 +24,30 @@ import org.springframework.ws.context.MessageContext; import org.springframework.ws.server.EndpointInterceptor; import org.springframework.ws.server.EndpointInvocationChain; -import org.springframework.ws.server.endpoint.mapping.AbstractAnnotationEndpointMapping; +import org.springframework.ws.server.endpoint.mapping.AbstractAnnotationMethodEndpointMapping; import org.springframework.ws.soap.SoapEndpointMapping; import org.springframework.ws.soap.SoapMessage; import org.springframework.ws.soap.server.SoapEndpointInvocationChain; import org.springframework.ws.soap.server.endpoint.annotation.SoapAction; /** - * Implementation of the EndpointMapping interface to map from SOAPAction headers to endpoint - * beans. Supports both mapping to bean instances and mapping to bean names: the latter is required for prototype - * handlers. + * Implementation of the {@link org.springframework.ws.server.EndpointMapping} interface that uses the {@link + * SoapAction} annotation to map methods to the request SOAPAction header. *

- * The endpointMap property is suitable for populating the endpoint map with bean references, e.g. via the - * map element in XML bean definitions. - *

- * Mappings to bean names can be set via the mappings property, in a form accepted by the - * java.util.Properties class, like as follows: + * Endpoints typically have the following form: *

- * http://www.springframework.org/spring-ws/samples/airline/BookFlight=bookFlightEndpoint
- * http://www.springframework.org/spring-ws/samples/airline/GetFlights=getFlightsEndpoint
+ * @Endpoint
+ * public class MyEndpoint{
+ *    @SoapAction("http://springframework.org/spring-ws/SoapAction")
+ *    public Source doSomethingWithRequest() {
+ *       ...
+ *    }
+ * }
  * 
- * The syntax is SOAP_ACTION=ENDPOINT_BEAN_NAME. - *

- * This endpoint mapping does not read from the request message, and therefore is more suitable for message contexts - * which directly read from the transport request (such as the AxiomSoapMessageContextFactory with the - * payloadCaching disabled). * * @author Arjen Poutsma */ -public class SoapActionAnnotationEndpointMapping extends AbstractAnnotationEndpointMapping +public class SoapActionAnnotationMethodEndpointMapping extends AbstractAnnotationMethodEndpointMapping implements SoapEndpointMapping { private String[] actorsOrRoles; diff --git a/sandbox/src/test/java/org/springframework/ws/server/endpoint/adapter/XPathParamAnnotationEndpointAdapterTest.java b/core-tiger/src/test/java/org/springframework/ws/server/endpoint/adapter/XPathParamAnnotationEndpointAdapterTest.java similarity index 75% rename from sandbox/src/test/java/org/springframework/ws/server/endpoint/adapter/XPathParamAnnotationEndpointAdapterTest.java rename to core-tiger/src/test/java/org/springframework/ws/server/endpoint/adapter/XPathParamAnnotationEndpointAdapterTest.java index 6e08cd103..1802ead64 100644 --- a/sandbox/src/test/java/org/springframework/ws/server/endpoint/adapter/XPathParamAnnotationEndpointAdapterTest.java +++ b/core-tiger/src/test/java/org/springframework/ws/server/endpoint/adapter/XPathParamAnnotationEndpointAdapterTest.java @@ -19,19 +19,22 @@ import javax.xml.transform.Source; import junit.framework.TestCase; -import org.springframework.core.io.ClassPathResource; -import org.springframework.ws.MockWebServiceMessage; -import org.springframework.ws.MockWebServiceMessageFactory; +import org.easymock.MockControl; +import org.springframework.ws.WebServiceMessage; +import org.springframework.ws.WebServiceMessageFactory; import org.springframework.ws.context.DefaultMessageContext; import org.springframework.ws.context.MessageContext; import org.springframework.ws.server.endpoint.MethodEndpoint; import org.springframework.ws.server.endpoint.annotation.XPathParam; +import org.springframework.xml.transform.StringResult; import org.springframework.xml.transform.StringSource; import org.w3c.dom.Node; import org.w3c.dom.NodeList; public class XPathParamAnnotationEndpointAdapterTest extends TestCase { + private static final String CONTENTS = "text42.0"; + private XPathParamAnnotationEndpointAdapter adapter; private boolean supportedTypesInvoked = false; @@ -81,22 +84,44 @@ public void testSupportsVoid() throws NoSuchMethodException { } public void testInvokeTypes() throws Exception { - MockWebServiceMessage request = - new MockWebServiceMessage(new ClassPathResource("nonamespaces.xml", getClass())); - MessageContext messageContext = new DefaultMessageContext(request, new MockWebServiceMessageFactory()); + MockControl messageControl = MockControl.createControl(WebServiceMessage.class); + WebServiceMessage messageMock = (WebServiceMessage) messageControl.getMock(); + messageControl.expectAndReturn(messageMock.getPayloadSource(), new StringSource(CONTENTS)); + messageControl.replay(); + MockControl factoryControl = MockControl.createControl(WebServiceMessageFactory.class); + WebServiceMessageFactory factoryMock = (WebServiceMessageFactory) factoryControl.getMock(); + factoryControl.replay(); + + MessageContext messageContext = new DefaultMessageContext(messageMock, factoryMock); MethodEndpoint endpoint = new MethodEndpoint(this, "supportedTypes", new Class[]{Boolean.TYPE, Double.TYPE, Node.class, NodeList.class, String.class}); adapter.invoke(messageContext, endpoint); assertTrue("Method not invoked", supportedTypesInvoked); + + messageControl.verify(); + factoryControl.verify(); + } public void testInvokeSource() throws Exception { - MockWebServiceMessage request = - new MockWebServiceMessage(new ClassPathResource("nonamespaces.xml", getClass())); - MessageContext messageContext = new DefaultMessageContext(request, new MockWebServiceMessageFactory()); + MockControl messageControl = MockControl.createControl(WebServiceMessage.class); + WebServiceMessage requestMock = (WebServiceMessage) messageControl.getMock(); + WebServiceMessage responseMock = (WebServiceMessage) messageControl.getMock(); + messageControl.expectAndReturn(requestMock.getPayloadSource(), new StringSource(CONTENTS)); + messageControl.expectAndReturn(responseMock.getPayloadResult(), new StringResult()); + messageControl.replay(); + MockControl factoryControl = MockControl.createControl(WebServiceMessageFactory.class); + WebServiceMessageFactory factoryMock = (WebServiceMessageFactory) factoryControl.getMock(); + factoryControl.expectAndReturn(factoryMock.createWebServiceMessage(), responseMock); + factoryControl.replay(); + + MessageContext messageContext = new DefaultMessageContext(requestMock, factoryMock); MethodEndpoint endpoint = new MethodEndpoint(this, "supportedSource", new Class[]{String.class}); adapter.invoke(messageContext, endpoint); assertTrue("Method not invoked", supportedSourceInvoked); + + messageControl.verify(); + factoryControl.verify(); } public void supportedVoid(@XPathParam("/")String param1) { diff --git a/sandbox/src/test/java/org/springframework/ws/server/endpoint/mapping/AnnotationEndpointMappingTest.java b/core-tiger/src/test/java/org/springframework/ws/server/endpoint/mapping/PayloadRootAnnotationMethodEndpointMappingTest.java similarity index 52% rename from sandbox/src/test/java/org/springframework/ws/server/endpoint/mapping/AnnotationEndpointMappingTest.java rename to core-tiger/src/test/java/org/springframework/ws/server/endpoint/mapping/PayloadRootAnnotationMethodEndpointMappingTest.java index 934210d3e..df3b9044f 100644 --- a/sandbox/src/test/java/org/springframework/ws/server/endpoint/mapping/AnnotationEndpointMappingTest.java +++ b/core-tiger/src/test/java/org/springframework/ws/server/endpoint/mapping/PayloadRootAnnotationMethodEndpointMappingTest.java @@ -16,73 +16,41 @@ package org.springframework.ws.server.endpoint.mapping; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import java.lang.reflect.Method; - import junit.framework.TestCase; import org.springframework.context.support.StaticApplicationContext; -import org.springframework.core.annotation.AnnotationUtils; -import org.springframework.ws.context.MessageContext; import org.springframework.ws.server.endpoint.MethodEndpoint; import org.springframework.ws.server.endpoint.annotation.Endpoint; +import org.springframework.ws.server.endpoint.annotation.PayloadRoot; -/** TestCase for {@link AbstractAnnotationEndpointMapping} */ -public class AnnotationEndpointMappingTest extends TestCase { +public class PayloadRootAnnotationMethodEndpointMappingTest extends TestCase { - private AbstractAnnotationEndpointMapping mapping; + private PayloadRootAnnotationMethodEndpointMapping mapping; private StaticApplicationContext applicationContext; protected void setUp() throws Exception { applicationContext = new StaticApplicationContext(); - applicationContext.registerSingleton("mapping", MyAnnotationEndpointMapping.class); + applicationContext.registerSingleton("mapping", PayloadRootAnnotationMethodEndpointMapping.class); applicationContext.registerSingleton("endpoint", MyEndpoint.class); applicationContext.registerSingleton("other", OtherBean.class); applicationContext.refresh(); - mapping = (AbstractAnnotationEndpointMapping) applicationContext.getBean("mapping"); + mapping = (PayloadRootAnnotationMethodEndpointMapping) applicationContext.getBean("mapping"); } public void testRegistration() throws NoSuchMethodException { - MethodEndpoint endpoint = mapping.lookupEndpoint("arg"); + MethodEndpoint endpoint = mapping.lookupEndpoint("{http://springframework.org/spring-ws}Request"); assertNotNull("MethodEndpoint not registered", endpoint); MethodEndpoint expected = new MethodEndpoint(applicationContext.getBean("endpoint"), "doIt", new Class[0]); assertEquals("Invalid endpoint registered", expected, endpoint); - assertNull("Invalid endpoint registered", mapping.lookupEndpoint("arg2")); - } - - private static class MyAnnotationEndpointMapping extends AbstractAnnotationEndpointMapping { - - protected String getLookupKeyForMethod(Method method) { - MyAnnotation annotation = AnnotationUtils.getAnnotation(method, MyAnnotation.class); - if (annotation != null) { - return annotation.value(); - } - else { - return null; - } - } - - protected String getLookupKeyForMessage(MessageContext messageContext) throws Exception { - return "arg"; - } - } - - @Target(ElementType.METHOD) - @Retention(RetentionPolicy.RUNTIME) - public @interface MyAnnotation { - - String value(); - + assertNull("Invalid endpoint registered", + mapping.lookupEndpoint("{http://springframework.org/spring-ws}Request2")); } @Endpoint private static class MyEndpoint { - @MyAnnotation("arg") + @PayloadRoot("{http://springframework.org/spring-ws}Request") public void doIt() { } @@ -91,7 +59,7 @@ public void doIt() { private static class OtherBean { - @MyAnnotation("arg2") + @PayloadRoot("{http://springframework.org/spring-ws}Request2") public void doIt() { } diff --git a/core-tiger/src/test/java/org/springframework/ws/soap/server/endpoint/mapping/SoapActionAnnotationMethodEndpointMappingTest.java b/core-tiger/src/test/java/org/springframework/ws/soap/server/endpoint/mapping/SoapActionAnnotationMethodEndpointMappingTest.java new file mode 100644 index 000000000..ac5e94544 --- /dev/null +++ b/core-tiger/src/test/java/org/springframework/ws/soap/server/endpoint/mapping/SoapActionAnnotationMethodEndpointMappingTest.java @@ -0,0 +1,72 @@ +/* + * Copyright 2007 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.server.endpoint.mapping; + +import junit.framework.TestCase; +import org.easymock.MockControl; +import org.springframework.context.support.StaticApplicationContext; +import org.springframework.ws.WebServiceMessageFactory; +import org.springframework.ws.context.DefaultMessageContext; +import org.springframework.ws.context.MessageContext; +import org.springframework.ws.server.EndpointInvocationChain; +import org.springframework.ws.server.endpoint.MethodEndpoint; +import org.springframework.ws.server.endpoint.annotation.Endpoint; +import org.springframework.ws.soap.SoapMessage; +import org.springframework.ws.soap.server.endpoint.annotation.SoapAction; + +public class SoapActionAnnotationMethodEndpointMappingTest extends TestCase { + + private SoapActionAnnotationMethodEndpointMapping mapping; + + private StaticApplicationContext applicationContext; + + protected void setUp() throws Exception { + applicationContext = new StaticApplicationContext(); + applicationContext.registerSingleton("mapping", SoapActionAnnotationMethodEndpointMapping.class); + applicationContext.registerSingleton("endpoint", MyEndpoint.class); + applicationContext.refresh(); + mapping = (SoapActionAnnotationMethodEndpointMapping) applicationContext.getBean("mapping"); + } + + public void testRegistration() throws Exception { + MockControl messageControl = MockControl.createControl(SoapMessage.class); + SoapMessage requestMock = (SoapMessage) messageControl.getMock(); + messageControl.expectAndReturn(requestMock.getSoapAction(), "http://springframework.org/spring-ws/SoapAction"); + messageControl.replay(); + MockControl factoryControl = MockControl.createControl(WebServiceMessageFactory.class); + WebServiceMessageFactory factoryMock = (WebServiceMessageFactory) factoryControl.getMock(); + factoryControl.replay(); + MessageContext context = new DefaultMessageContext(requestMock, factoryMock); + + EndpointInvocationChain chain = mapping.getEndpoint(context); + assertNotNull("MethodEndpoint not registered", chain); + MethodEndpoint expected = new MethodEndpoint(applicationContext.getBean("endpoint"), "doIt", new Class[0]); + assertEquals("Invalid endpoint registered", expected, chain.getEndpoint()); + messageControl.verify(); + factoryControl.verify(); + } + + @Endpoint + private static class MyEndpoint { + + @SoapAction("http://springframework.org/spring-ws/SoapAction") + public void doIt() { + + } + + } +} \ No newline at end of file diff --git a/core-tiger/src/test/resources/log4j.properties b/core-tiger/src/test/resources/log4j.properties new file mode 100644 index 000000000..92e896c8d --- /dev/null +++ b/core-tiger/src/test/resources/log4j.properties @@ -0,0 +1,6 @@ +log4j.rootCategory=INFO, stdout +log4j.logger.org.springframework.ws=DEBUG + +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n \ No newline at end of file diff --git a/core/pom.xml b/core/pom.xml index 42025add6..fba171491 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -1,5 +1,6 @@ - + spring-ws org.springframework.ws @@ -33,6 +34,10 @@ org.springframework spring-webmvc + + org.springframework + spring-aop + org.springframework spring-mock diff --git a/sandbox/src/main/java/org/springframework/ws/server/endpoint/MethodEndpoint.java b/core/src/main/java/org/springframework/ws/server/endpoint/MethodEndpoint.java similarity index 100% rename from sandbox/src/main/java/org/springframework/ws/server/endpoint/MethodEndpoint.java rename to core/src/main/java/org/springframework/ws/server/endpoint/MethodEndpoint.java diff --git a/sandbox/src/main/java/org/springframework/ws/server/endpoint/adapter/AbstractMethodEndpointAdapter.java b/core/src/main/java/org/springframework/ws/server/endpoint/adapter/AbstractMethodEndpointAdapter.java similarity index 95% rename from sandbox/src/main/java/org/springframework/ws/server/endpoint/adapter/AbstractMethodEndpointAdapter.java rename to core/src/main/java/org/springframework/ws/server/endpoint/adapter/AbstractMethodEndpointAdapter.java index 4e8bc7326..ee376b795 100644 --- a/sandbox/src/main/java/org/springframework/ws/server/endpoint/adapter/AbstractMethodEndpointAdapter.java +++ b/core/src/main/java/org/springframework/ws/server/endpoint/adapter/AbstractMethodEndpointAdapter.java @@ -24,8 +24,8 @@ import org.springframework.xml.transform.TransformerObjectSupport; /** - * Abstract base class for {@link EndpointAdapter} implementations that support {@link - * org.springframework.ws.server.endpoint.MethodEndpoint}s. Contains template methods for handling method endpoints. + * Abstract base class for {@link EndpointAdapter} implementations that support {@link MethodEndpoint}s. Contains + * template methods for handling these method endpoints. * * @author Arjen Poutsma */ diff --git a/sandbox/src/main/java/org/springframework/ws/server/endpoint/mapping/AbstractMethodEndpointMapping.java b/core/src/main/java/org/springframework/ws/server/endpoint/mapping/AbstractMethodEndpointMapping.java similarity index 100% rename from sandbox/src/main/java/org/springframework/ws/server/endpoint/mapping/AbstractMethodEndpointMapping.java rename to core/src/main/java/org/springframework/ws/server/endpoint/mapping/AbstractMethodEndpointMapping.java diff --git a/core/src/main/java/org/springframework/ws/server/endpoint/mapping/PayloadRootQNameEndpointMapping.java b/core/src/main/java/org/springframework/ws/server/endpoint/mapping/PayloadRootQNameEndpointMapping.java index e88f3a982..b959aa0e9 100644 --- a/core/src/main/java/org/springframework/ws/server/endpoint/mapping/PayloadRootQNameEndpointMapping.java +++ b/core/src/main/java/org/springframework/ws/server/endpoint/mapping/PayloadRootQNameEndpointMapping.java @@ -17,13 +17,11 @@ package org.springframework.ws.server.endpoint.mapping; import javax.xml.namespace.QName; -import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; -import javax.xml.transform.dom.DOMResult; -import org.springframework.ws.WebServiceMessage; import org.springframework.ws.context.MessageContext; +import org.springframework.xml.dom.DomUtils; import org.springframework.xml.namespace.QNameUtils; import org.w3c.dom.Element; @@ -56,15 +54,10 @@ public class PayloadRootQNameEndpointMapping extends AbstractQNameEndpointMappin } protected QName resolveQName(MessageContext messageContext) throws TransformerException { - Element payloadElement = getMessagePayloadElement(messageContext.getRequest()); + Element payloadElement = + DomUtils.getRootElement(messageContext.getRequest().getPayloadSource(), transformerFactory); return QNameUtils.getQNameForNode(payloadElement); } - private Element getMessagePayloadElement(WebServiceMessage message) throws TransformerException { - Transformer transformer = transformerFactory.newTransformer(); - DOMResult domResult = new DOMResult(); - transformer.transform(message.getPayloadSource(), domResult); - return (Element) domResult.getNode().getFirstChild(); - } } diff --git a/core/src/main/java/org/springframework/ws/transport/http/CommonsHttpMessageSender.java b/core/src/main/java/org/springframework/ws/transport/http/CommonsHttpMessageSender.java index db835c78e..467da0658 100644 --- a/core/src/main/java/org/springframework/ws/transport/http/CommonsHttpMessageSender.java +++ b/core/src/main/java/org/springframework/ws/transport/http/CommonsHttpMessageSender.java @@ -31,7 +31,6 @@ * Commons HttpClient to execute POST requests. *

* Allows to use a preconfigured HttpClient instance, potentially with authentication, HTTP connection pooling, etc. - * Also designed for easy subclassing, customizing specific template methods. * * @author Arjen Poutsma * @see org.springframework.ws.transport.http.HttpUrlConnectionMessageSender diff --git a/sandbox/src/test/java/org/springframework/ws/server/endpoint/MethodEndpointTest.java b/core/src/test/java/org/springframework/ws/server/endpoint/MethodEndpointTest.java similarity index 100% rename from sandbox/src/test/java/org/springframework/ws/server/endpoint/MethodEndpointTest.java rename to core/src/test/java/org/springframework/ws/server/endpoint/MethodEndpointTest.java diff --git a/pom.xml b/pom.xml index 771a3f9f6..ddcacf1c1 100644 --- a/pom.xml +++ b/pom.xml @@ -104,6 +104,7 @@ oxm-tiger + core-tiger diff --git a/sandbox/src/test/java/org/springframework/ws/soap/server/endpoint/mapping/SoapActionAnnotationEndpointMappingTest.java b/sandbox/src/test/java/org/springframework/ws/soap/server/endpoint/mapping/SoapActionAnnotationEndpointMappingTest.java deleted file mode 100644 index 806baf170..000000000 --- a/sandbox/src/test/java/org/springframework/ws/soap/server/endpoint/mapping/SoapActionAnnotationEndpointMappingTest.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2007 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.server.endpoint.mapping; - -import junit.framework.TestCase; -import org.springframework.context.support.StaticApplicationContext; -import org.springframework.ws.server.endpoint.annotation.Endpoint; -import org.springframework.ws.soap.server.endpoint.annotation.SoapAction; - -public class SoapActionAnnotationEndpointMappingTest extends TestCase { - - private StaticApplicationContext applicationContext; - - private SoapActionAnnotationEndpointMapping mapping; - - protected void setUp() throws Exception { - applicationContext = new StaticApplicationContext(); - applicationContext.registerSingleton("mapping", SoapActionAnnotationEndpointMapping.class); - applicationContext.registerSingleton("endpoint", MyEndpoint.class); - applicationContext.refresh(); - mapping = (SoapActionAnnotationEndpointMapping) applicationContext.getBean("mapping"); - } - - public void testIt() { - - } - - @Endpoint - private static class MyEndpoint { - - @SoapAction("http://springframework.org/spring-ws/action") - public void handleMessage() { - - } - } -} \ No newline at end of file diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 67de63131..1d8cbb819 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -6,6 +6,9 @@ + Added MethodEndpoint functionality, invoking methods for + incoming requests + GZip compression is not enabled WebServiceConnection is now container for TransportInputStream and TransportOutputStream, used on both client- and server-side diff --git a/xml/src/main/java/org/springframework/xml/dom/DomUtils.java b/xml/src/main/java/org/springframework/xml/dom/DomUtils.java index 0a1573ce0..9b1996d4e 100644 --- a/xml/src/main/java/org/springframework/xml/dom/DomUtils.java +++ b/xml/src/main/java/org/springframework/xml/dom/DomUtils.java @@ -19,6 +19,7 @@ import javax.xml.transform.Source; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMResult; import javax.xml.transform.dom.DOMSource; @@ -36,11 +37,12 @@ public abstract class DomUtils { /** * Returns the root element of the given source, transforming it if necessary. * - * @param source the source to get the root element from - * @param transformer a transformer + * @param source the source to get the root element from + * @param transformerFactory a transformer factory, necessary if the given source is not a DOMSource * @return the root element */ - public static Element getRootElement(Source source, Transformer transformer) throws TransformerException { + public static Element getRootElement(Source source, TransformerFactory transformerFactory) + throws TransformerException { if (source instanceof DOMSource) { DOMSource domSource = (DOMSource) source; Node node = domSource.getNode(); @@ -55,6 +57,7 @@ else if (node.getNodeType() == Node.DOCUMENT_NODE) { return document.getDocumentElement(); } } + Transformer transformer = transformerFactory.newTransformer(); DOMResult domResult = new DOMResult(); transformer.transform(source, domResult); Document document = (Document) domResult.getNode(); diff --git a/xml/src/main/java/org/springframework/xml/transform/TransformerObjectSupport.java b/xml/src/main/java/org/springframework/xml/transform/TransformerObjectSupport.java index 461bace6e..2e92afef6 100644 --- a/xml/src/main/java/org/springframework/xml/transform/TransformerObjectSupport.java +++ b/xml/src/main/java/org/springframework/xml/transform/TransformerObjectSupport.java @@ -34,9 +34,7 @@ */ public abstract class TransformerObjectSupport { - /** - * Logger available to subclasses. - */ + /** Logger available to subclasses. */ protected final Log logger = LogFactory.getLog(getClass()); private static TransformerFactory transformerFactory; @@ -45,6 +43,11 @@ public abstract class TransformerObjectSupport { transformerFactory = TransformerFactory.newInstance(); } + /** Returns the TransformerFactory. */ + protected TransformerFactory getTransformerFactory() { + return transformerFactory; + } + /** * Creates a new Transformer. Must be called per request, as transformer is not thread-safe. * diff --git a/xml/src/test/java/org/springframework/xml/dom/DomUtilsTest.java b/xml/src/test/java/org/springframework/xml/dom/DomUtilsTest.java index 1104ec5ed..dff9e604d 100644 --- a/xml/src/test/java/org/springframework/xml/dom/DomUtilsTest.java +++ b/xml/src/test/java/org/springframework/xml/dom/DomUtilsTest.java @@ -20,7 +20,6 @@ import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.Source; -import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; @@ -34,16 +33,16 @@ public class DomUtilsTest extends TestCase { - private Transformer transformer; - private static final String NAMESPACE = "http://springframework.org/spring-ws"; private static final String LOCAL_NAME = "Root"; private static final String XML = "<" + LOCAL_NAME + " xmlns='" + NAMESPACE + "'/>"; + private TransformerFactory transformerFactory; + protected void setUp() throws Exception { - transformer = TransformerFactory.newInstance().newTransformer(); + transformerFactory = TransformerFactory.newInstance(); } public void testGetRootElementDomSource() throws Exception { @@ -67,7 +66,7 @@ public void testGetRootElementStreamSource() throws Exception { } private void testSource(Source source) throws TransformerException { - Element result = DomUtils.getRootElement(source, transformer); + Element result = DomUtils.getRootElement(source, transformerFactory); assertNotNull("No result", result); assertEquals("Invalid namespace", NAMESPACE, result.getNamespaceURI()); assertEquals("Invalid local name", LOCAL_NAME, result.getLocalName());