diff --git a/core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/AbstractPayloadMethodProcessor.java b/core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/AbstractPayloadMethodProcessor.java index 2feaeb7f..2b6ae351 100644 --- a/core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/AbstractPayloadMethodProcessor.java +++ b/core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/AbstractPayloadMethodProcessor.java @@ -16,7 +16,11 @@ package org.springframework.ws.server.endpoint.adapter.method; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import javax.xml.transform.Source; +import javax.xml.transform.TransformerException; +import javax.xml.transform.stream.StreamResult; import org.springframework.core.MethodParameter; import org.springframework.util.Assert; @@ -132,4 +136,18 @@ public abstract class AbstractPayloadMethodProcessor extends TransformerObjectSu * @throws Exception in case of errors */ protected abstract Source createResponsePayload(MethodParameter returnType, Object returnValue); + + /** + * Converts the given source to a byte array input stream. + * + * @param source the source to convert + * @return the input stream + * @throws TransformerException in case of transformation errors + */ + protected ByteArrayInputStream convertToByteArrayInputStream(Source source) throws TransformerException { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + transform(source, new StreamResult(bos)); + return new ByteArrayInputStream(bos.toByteArray()); + } + } diff --git a/core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/DomMethodArgumentProcessor.java b/core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/DomPayloadMethodProcessor.java similarity index 97% rename from core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/DomMethodArgumentProcessor.java rename to core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/DomPayloadMethodProcessor.java index 3c7c1f25..e35df050 100644 --- a/core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/DomMethodArgumentProcessor.java +++ b/core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/DomPayloadMethodProcessor.java @@ -33,7 +33,7 @@ import org.w3c.dom.Node; * @author Arjen Poutsma * @since 2.0 */ -public class DomMethodArgumentProcessor extends AbstractPayloadMethodProcessor { +public class DomPayloadMethodProcessor extends AbstractPayloadMethodProcessor { // MethodArgumentResolver diff --git a/core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/SourcePayloadMethodProcessor.java b/core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/SourcePayloadMethodProcessor.java new file mode 100644 index 00000000..d8b7d165 --- /dev/null +++ b/core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/SourcePayloadMethodProcessor.java @@ -0,0 +1,95 @@ +/* + * Copyright 2005-2010 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.server.endpoint.adapter.method; + +import java.io.ByteArrayInputStream; +import javax.xml.transform.Source; +import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.sax.SAXSource; +import javax.xml.transform.stream.StreamSource; + +import org.springframework.core.MethodParameter; + +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.xml.sax.InputSource; + +/** + * Implementation of {@link MethodArgumentResolver} and {@link MethodReturnValueHandler} that supports {@link Source} + * objects. + * + * @author Arjen Poutsma + * @since 2.0 + */ +public class SourcePayloadMethodProcessor extends AbstractPayloadMethodProcessor { + + // MethodArgumentResolver + + @Override + protected boolean supportsRequestPayloadParameter(MethodParameter parameter) { + return supports(parameter); + } + + @Override + protected Object resolveRequestPayloadArgument(Source requestPayload, MethodParameter parameter) throws Exception { + Class parameterType = parameter.getParameterType(); + if (parameterType.isAssignableFrom(requestPayload.getClass())) { + return requestPayload; + } + if (DOMSource.class.isAssignableFrom(parameterType)) { + DOMResult domResult = new DOMResult(); + transform(requestPayload, domResult); + Node node = domResult.getNode(); + if (node instanceof Document) { + Document document = (Document) node; + return new DOMSource(document.getDocumentElement()); + } + else { + return new DOMSource(domResult.getNode()); + } + } + else if (SAXSource.class.isAssignableFrom(parameterType)) { + ByteArrayInputStream bis = convertToByteArrayInputStream(requestPayload); + InputSource inputSource = new InputSource(bis); + return new SAXSource(inputSource); + } + else if (StreamSource.class.isAssignableFrom(parameterType)) { + ByteArrayInputStream bis = convertToByteArrayInputStream(requestPayload); + return new StreamSource(bis); + } + // should not happen + throw new UnsupportedOperationException(); + } + + // MethodReturnValueHandler + + @Override + protected boolean supportsResponsePayloadReturnType(MethodParameter returnType) { + return supports(returnType); + } + + @Override + protected Source createResponsePayload(MethodParameter returnType, Object returnValue) { + return (Source) returnValue; + } + + private boolean supports(MethodParameter parameter) { + return Source.class.isAssignableFrom(parameter.getParameterType()); + } + +} diff --git a/core/src/test/java/org/springframework/ws/server/endpoint/adapter/method/AbstractPayloadMethodProcessorTest.java b/core/src/test/java/org/springframework/ws/server/endpoint/adapter/method/AbstractPayloadMethodProcessorTest.java index 38bb58ae..a1dd56b5 100644 --- a/core/src/test/java/org/springframework/ws/server/endpoint/adapter/method/AbstractPayloadMethodProcessorTest.java +++ b/core/src/test/java/org/springframework/ws/server/endpoint/adapter/method/AbstractPayloadMethodProcessorTest.java @@ -44,7 +44,7 @@ public abstract class AbstractPayloadMethodProcessorTest extends TransformerObje protected static final String LOCAL_NAME = "request"; - private static final String REQUEST = "<" + LOCAL_NAME + " xmlns=\"" + NAMESPACE_URI + "\"/>"; + protected static final String XML = "<" + LOCAL_NAME + " xmlns=\"" + NAMESPACE_URI + "\"/>"; protected AbstractPayloadMethodProcessor processor; @@ -111,12 +111,15 @@ public abstract class AbstractPayloadMethodProcessorTest extends TransformerObje for (MethodParameter supportedParameter : supportedParameters) { Object argument = processor.resolveArgument(messageContext, supportedParameter); + assertTrue(argument + " is not an instance of " + supportedParameter.getParameterType(), + supportedParameter.getParameterType().isInstance(argument)); testArgument(argument, supportedParameter); } } - protected abstract void testArgument(Object argument, MethodParameter parameter); + protected void testArgument(Object argument, MethodParameter parameter) { + } @Test public void saajReturnValue() throws Exception { @@ -157,14 +160,14 @@ public abstract class AbstractPayloadMethodProcessorTest extends TransformerObje } protected MessageContext createMockMessageContext() throws TransformerException { - MockWebServiceMessage request = new MockWebServiceMessage(new StringSource(REQUEST)); + MockWebServiceMessage request = new MockWebServiceMessage(new StringSource(XML)); return new DefaultMessageContext(request, new MockWebServiceMessageFactory()); } protected MessageContext createCachingAxiomMessageContext() throws Exception { SOAPFactory axiomFactory = OMAbstractFactory.getSOAP11Factory(); AxiomSoapMessage request = new AxiomSoapMessage(axiomFactory, true, false); - transform(new StringSource(REQUEST), request.getPayloadResult()); + transform(new StringSource(XML), request.getPayloadResult()); AxiomSoapMessageFactory soapMessageFactory = new AxiomSoapMessageFactory(); soapMessageFactory.afterPropertiesSet(); return new DefaultMessageContext(request, soapMessageFactory); @@ -173,7 +176,7 @@ public abstract class AbstractPayloadMethodProcessorTest extends TransformerObje protected MessageContext createNonCachingAxiomMessageContext() throws Exception { SOAPFactory axiomFactory = OMAbstractFactory.getSOAP11Factory(); AxiomSoapMessage request = new AxiomSoapMessage(axiomFactory, false, false); - transform(new StringSource(REQUEST), request.getPayloadResult()); + transform(new StringSource(XML), request.getPayloadResult()); AxiomSoapMessageFactory soapMessageFactory = new AxiomSoapMessageFactory(); soapMessageFactory.setPayloadCaching(false); soapMessageFactory.afterPropertiesSet(); diff --git a/core/src/test/java/org/springframework/ws/server/endpoint/adapter/method/DomMethodArgumentProcessorTest.java b/core/src/test/java/org/springframework/ws/server/endpoint/adapter/method/DomPayloadMethodProcessorTest.java similarity index 95% rename from core/src/test/java/org/springframework/ws/server/endpoint/adapter/method/DomMethodArgumentProcessorTest.java rename to core/src/test/java/org/springframework/ws/server/endpoint/adapter/method/DomPayloadMethodProcessorTest.java index a2743e35..8ab7348e 100644 --- a/core/src/test/java/org/springframework/ws/server/endpoint/adapter/method/DomMethodArgumentProcessorTest.java +++ b/core/src/test/java/org/springframework/ws/server/endpoint/adapter/method/DomPayloadMethodProcessorTest.java @@ -31,11 +31,11 @@ import org.w3c.dom.Node; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -public class DomMethodArgumentProcessorTest extends AbstractPayloadMethodProcessorTest { +public class DomPayloadMethodProcessorTest extends AbstractPayloadMethodProcessorTest { @Override protected AbstractPayloadMethodProcessor createProcessor() { - return new DomMethodArgumentProcessor(); + return new DomPayloadMethodProcessor(); } @Override diff --git a/core/src/test/java/org/springframework/ws/server/endpoint/adapter/method/SourcePayloadMethodProcessorTest.java b/core/src/test/java/org/springframework/ws/server/endpoint/adapter/method/SourcePayloadMethodProcessorTest.java new file mode 100644 index 00000000..4eee49aa --- /dev/null +++ b/core/src/test/java/org/springframework/ws/server/endpoint/adapter/method/SourcePayloadMethodProcessorTest.java @@ -0,0 +1,79 @@ +/* + * Copyright 2005-2010 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.server.endpoint.adapter.method; + +import javax.xml.transform.Source; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.sax.SAXSource; +import javax.xml.transform.stream.StreamSource; + +import org.springframework.core.MethodParameter; +import org.springframework.ws.server.endpoint.annotation.RequestPayload; +import org.springframework.ws.server.endpoint.annotation.ResponsePayload; +import org.springframework.xml.transform.StringSource; + +/** @author Arjen Poutsma */ +public class SourcePayloadMethodProcessorTest extends AbstractPayloadMethodProcessorTest { + + @Override + protected AbstractPayloadMethodProcessor createProcessor() { + return new SourcePayloadMethodProcessor(); + } + + @Override + protected MethodParameter[] createSupportedParameters() throws NoSuchMethodException { + return new MethodParameter[] { + new MethodParameter(getClass().getMethod("source", Source.class), 0), + new MethodParameter(getClass().getMethod("dom", DOMSource.class), 0), + new MethodParameter(getClass().getMethod("sax", SAXSource.class), 0), + new MethodParameter(getClass().getMethod("stream", StreamSource.class), 0)}; + } + + @Override + protected MethodParameter[] createSupportedReturnTypes() throws NoSuchMethodException { + return new MethodParameter[] { + new MethodParameter(getClass().getMethod("source", Source.class), -1), + new MethodParameter(getClass().getMethod("dom", DOMSource.class), -1), + new MethodParameter(getClass().getMethod("sax", SAXSource.class), -1), + new MethodParameter(getClass().getMethod("stream", StreamSource.class), -1)}; + } + + @Override + protected Object getReturnValue(MethodParameter returnType) throws Exception { + return new StringSource(XML); + } + + @ResponsePayload + public Source source(@RequestPayload Source source) { + return source; + } + + @ResponsePayload + public DOMSource dom(@RequestPayload DOMSource source) { + return source; + } + + @ResponsePayload + public SAXSource sax(@RequestPayload SAXSource source) { + return source; + } + + @ResponsePayload + public StreamSource stream(@RequestPayload StreamSource source) { + return source; + } +}