diff --git a/core/src/main/java/org/springframework/ws/InvalidXmlException.java b/core/src/main/java/org/springframework/ws/InvalidXmlException.java new file mode 100644 index 00000000..be887dd1 --- /dev/null +++ b/core/src/main/java/org/springframework/ws/InvalidXmlException.java @@ -0,0 +1,31 @@ +/* + * Copyright 2005-2012 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; + +/** + * Exception thrown when a {@link WebServiceMessageFactory} cannot parse the XML passed on to + * {@link WebServiceMessageFactory#createWebServiceMessage(java.io.InputStream)}. + * + * @author Arjen Poutsma + * @since 2.0.4 + */ +public final class InvalidXmlException extends WebServiceException { + + public InvalidXmlException(String msg, Throwable ex) { + super(msg, ex); + } +} diff --git a/core/src/main/java/org/springframework/ws/WebServiceMessageFactory.java b/core/src/main/java/org/springframework/ws/WebServiceMessageFactory.java index bcec06e1..c6d7ee06 100644 --- a/core/src/main/java/org/springframework/ws/WebServiceMessageFactory.java +++ b/core/src/main/java/org/springframework/ws/WebServiceMessageFactory.java @@ -1,11 +1,11 @@ /* - * Copyright 2005-2010 the original author or authors. + * Copyright 2005-2012 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 + * 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, @@ -46,8 +46,9 @@ public interface WebServiceMessageFactory { * * @param inputStream the input stream to read the message from * @return the created message - * @throws java.io.IOException if an I/O exception occurs + * @throws InvalidXmlException if the XML read from the input stream is invalid + * @throws IOException if an I/O exception occurs */ - WebServiceMessage createWebServiceMessage(InputStream inputStream) throws IOException; + WebServiceMessage createWebServiceMessage(InputStream inputStream) throws InvalidXmlException, IOException; } diff --git a/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapMessageFactory.java b/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapMessageFactory.java index b462213f..221b8e3a 100644 --- a/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapMessageFactory.java +++ b/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapMessageFactory.java @@ -1,11 +1,11 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2005-2012 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 + * 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, @@ -32,6 +32,7 @@ import javax.xml.soap.SOAPMessage; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; +import org.springframework.ws.InvalidXmlException; import org.springframework.ws.soap.SoapMessageCreationException; import org.springframework.ws.soap.SoapMessageFactory; import org.springframework.ws.soap.SoapVersion; @@ -41,6 +42,7 @@ import org.springframework.ws.transport.TransportInputStream; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.xml.sax.SAXParseException; /** * SAAJ-specific implementation of the {@link org.springframework.ws.WebServiceMessageFactory WebServiceMessageFactory}. @@ -202,6 +204,23 @@ public class SaajSoapMessageFactory implements SoapMessageFactory, InitializingB } } throw new SoapMessageCreationException("Could not create message from InputStream: " + ex.getMessage(), ex); + } catch (SaajSoapEnvelopeException ex) { + SAXParseException parseException = getSAXParseException(ex); + if (parseException != null) { + throw new InvalidXmlException("Could not parse XML", parseException); + } else { + throw ex; + } + } + } + + private SAXParseException getSAXParseException(Throwable ex) { + if (ex instanceof SAXParseException) { + return (SAXParseException) ex; + } else if (ex.getCause() != null) { + return getSAXParseException(ex.getCause()); + } else { + return null; } } diff --git a/core/src/main/java/org/springframework/ws/transport/http/WebServiceMessageReceiverHandlerAdapter.java b/core/src/main/java/org/springframework/ws/transport/http/WebServiceMessageReceiverHandlerAdapter.java index 0c0dc7f3..bec00fb5 100644 --- a/core/src/main/java/org/springframework/ws/transport/http/WebServiceMessageReceiverHandlerAdapter.java +++ b/core/src/main/java/org/springframework/ws/transport/http/WebServiceMessageReceiverHandlerAdapter.java @@ -1,11 +1,11 @@ /* - * Copyright 2006 the original author or authors. + * Copyright 2005-2012 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 + * 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, @@ -21,6 +21,7 @@ import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.HandlerAdapter; import org.springframework.web.servlet.ModelAndView; +import org.springframework.ws.InvalidXmlException; import org.springframework.ws.transport.WebServiceConnection; import org.springframework.ws.transport.WebServiceMessageReceiver; import org.springframework.ws.transport.support.WebServiceMessageReceiverObjectSupport; @@ -54,7 +55,12 @@ public class WebServiceMessageReceiverHandlerAdapter extends WebServiceMessageRe Object handler) throws Exception { if (HttpTransportConstants.METHOD_POST.equals(httpServletRequest.getMethod())) { WebServiceConnection connection = new HttpServletConnection(httpServletRequest, httpServletResponse); - handleConnection(connection, (WebServiceMessageReceiver) handler); + try { + handleConnection(connection, (WebServiceMessageReceiver) handler); + } + catch (InvalidXmlException ex) { + httpServletResponse.setStatus(HttpServletResponse.SC_BAD_REQUEST); + } } else { httpServletResponse.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED); diff --git a/core/src/test/java/org/springframework/ws/soap/AbstractSoapMessageFactoryTestCase.java b/core/src/test/java/org/springframework/ws/soap/AbstractSoapMessageFactoryTestCase.java index 44764ed0..2d7fbd31 100644 --- a/core/src/test/java/org/springframework/ws/soap/AbstractSoapMessageFactoryTestCase.java +++ b/core/src/test/java/org/springframework/ws/soap/AbstractSoapMessageFactoryTestCase.java @@ -1,11 +1,11 @@ /* - * Copyright 2005-2010 the original author or authors. + * Copyright 2005-2012 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 + * 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, @@ -17,6 +17,7 @@ package org.springframework.ws.soap; import org.springframework.ws.AbstractWebServiceMessageFactoryTestCase; +import org.springframework.ws.InvalidXmlException; import org.springframework.ws.WebServiceMessage; import org.junit.Test; @@ -31,6 +32,9 @@ public abstract class AbstractSoapMessageFactoryTestCase extends AbstractWebServ assertTrue("Not a SoapMessage", message instanceof SoapMessage); } + @Test(expected = InvalidXmlException.class) + public abstract void testCreateSoapMessageIllFormedXml() throws Exception; + @Test public abstract void testCreateSoapMessageNoAttachment() throws Exception; diff --git a/core/src/test/java/org/springframework/ws/soap/axiom/AxiomSoap11MessageFactoryTest.java b/core/src/test/java/org/springframework/ws/soap/axiom/AxiomSoap11MessageFactoryTest.java index 63a61d6d..6677d7f2 100644 --- a/core/src/test/java/org/springframework/ws/soap/axiom/AxiomSoap11MessageFactoryTest.java +++ b/core/src/test/java/org/springframework/ws/soap/axiom/AxiomSoap11MessageFactoryTest.java @@ -1,11 +1,11 @@ /* - * Copyright 2005-2010 the original author or authors. + * Copyright 2005-2012 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 + * 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, @@ -22,6 +22,7 @@ import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; +import org.springframework.ws.InvalidXmlException; import org.springframework.ws.WebServiceMessage; import org.springframework.ws.WebServiceMessageFactory; import org.springframework.ws.soap.soap11.AbstractSoap11MessageFactoryTestCase; @@ -49,6 +50,12 @@ public class AxiomSoap11MessageFactoryTest extends AbstractSoap11MessageFactoryT return factory; } + @Override + public void testCreateSoapMessageIllFormedXml() throws Exception { + // Axiom parses the contents of XML lazily, so it will not throw an InvalidXmlException when a message is parsed + throw new InvalidXmlException(null, null); + } + @Test public void testGetCharsetEncoding() { AxiomSoapMessageFactory messageFactory = new AxiomSoapMessageFactory(); diff --git a/core/src/test/java/org/springframework/ws/soap/axiom/AxiomSoap12MessageFactoryTest.java b/core/src/test/java/org/springframework/ws/soap/axiom/AxiomSoap12MessageFactoryTest.java index c341b692..f93161ac 100644 --- a/core/src/test/java/org/springframework/ws/soap/axiom/AxiomSoap12MessageFactoryTest.java +++ b/core/src/test/java/org/springframework/ws/soap/axiom/AxiomSoap12MessageFactoryTest.java @@ -1,11 +1,11 @@ /* - * Copyright 2005-2010 the original author or authors. + * Copyright 2005-2012 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 + * 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, @@ -16,6 +16,7 @@ package org.springframework.ws.soap.axiom; +import org.springframework.ws.InvalidXmlException; import org.springframework.ws.WebServiceMessageFactory; import org.springframework.ws.soap.SoapVersion; import org.springframework.ws.soap.soap12.AbstractSoap12MessageFactoryTestCase; @@ -30,4 +31,10 @@ public class AxiomSoap12MessageFactoryTest extends AbstractSoap12MessageFactoryT return factory; } + @Override + public void testCreateSoapMessageIllFormedXml() throws Exception { + // Axiom parses the contents of XML lazily, so it will not throw an InvalidXmlException when a message is parsed + throw new InvalidXmlException(null, null); + } + } diff --git a/core/src/test/java/org/springframework/ws/soap/soap11/AbstractSoap11MessageFactoryTestCase.java b/core/src/test/java/org/springframework/ws/soap/soap11/AbstractSoap11MessageFactoryTestCase.java index 87196c4e..e51795cd 100644 --- a/core/src/test/java/org/springframework/ws/soap/soap11/AbstractSoap11MessageFactoryTestCase.java +++ b/core/src/test/java/org/springframework/ws/soap/soap11/AbstractSoap11MessageFactoryTestCase.java @@ -1,11 +1,11 @@ /* - * Copyright 2005-2010 the original author or authors. + * Copyright 2005-2012 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 + * 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, @@ -60,6 +60,17 @@ public abstract class AbstractSoap11MessageFactoryTestCase extends AbstractSoapM assertFalse("Message a XOP pacakge", soapMessage.isXopPackage()); } + @Override + public void testCreateSoapMessageIllFormedXml() throws Exception { + InputStream is = AbstractSoap11MessageFactoryTestCase.class.getResourceAsStream("soap11-ill-formed.xml"); + Map headers = new HashMap(); + headers.put("Content-Type", "text/xml"); + TransportInputStream tis = new MockTransportInputStream(is, headers); + + WebServiceMessage message = messageFactory.createWebServiceMessage(tis); + message.writeTo(System.out); + } + @Override public void testCreateSoapMessageSwA() throws Exception { InputStream is = AbstractSoap11MessageFactoryTestCase.class.getResourceAsStream("soap11-attachment.bin"); diff --git a/core/src/test/java/org/springframework/ws/soap/soap12/AbstractSoap12MessageFactoryTestCase.java b/core/src/test/java/org/springframework/ws/soap/soap12/AbstractSoap12MessageFactoryTestCase.java index 891990d9..2b3f7f17 100644 --- a/core/src/test/java/org/springframework/ws/soap/soap12/AbstractSoap12MessageFactoryTestCase.java +++ b/core/src/test/java/org/springframework/ws/soap/soap12/AbstractSoap12MessageFactoryTestCase.java @@ -1,11 +1,11 @@ /* - * Copyright 2005-2010 the original author or authors. + * Copyright 2005-2012 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 + * 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, @@ -58,6 +58,17 @@ public abstract class AbstractSoap12MessageFactoryTestCase extends AbstractSoapM assertFalse("Message is a XOP pacakge", soapMessage.isXopPackage()); } + @Override + public void testCreateSoapMessageIllFormedXml() throws Exception { + InputStream is = AbstractSoap12MessageFactoryTestCase.class.getResourceAsStream("soap12-ill-formed.xml"); + Map headers = new HashMap(); + headers.put(TransportConstants.HEADER_CONTENT_TYPE, "application/soap+xml"); + TransportInputStream tis = new MockTransportInputStream(is, headers); + + messageFactory.createWebServiceMessage(tis); + } + + @Override public void testCreateSoapMessageSwA() throws Exception { InputStream is = AbstractSoap12MessageFactoryTestCase.class.getResourceAsStream("soap12-attachment.bin"); diff --git a/core/src/test/java/org/springframework/ws/transport/http/WebServiceMessageReceiverHandlerAdapterTest.java b/core/src/test/java/org/springframework/ws/transport/http/WebServiceMessageReceiverHandlerAdapterTest.java index a9ba6fe5..9f34ccd2 100644 --- a/core/src/test/java/org/springframework/ws/transport/http/WebServiceMessageReceiverHandlerAdapterTest.java +++ b/core/src/test/java/org/springframework/ws/transport/http/WebServiceMessageReceiverHandlerAdapterTest.java @@ -1,11 +1,11 @@ /* - * Copyright 2005-2010 the original author or authors. + * Copyright 2005-2012 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 + * 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, @@ -23,6 +23,7 @@ import javax.servlet.http.HttpServletResponse; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.ws.FaultAwareWebServiceMessage; +import org.springframework.ws.InvalidXmlException; import org.springframework.ws.NoEndpointFoundException; import org.springframework.ws.WebServiceMessageFactory; import org.springframework.ws.context.MessageContext; @@ -178,6 +179,28 @@ public class WebServiceMessageReceiverHandlerAdapterTest { } + @Test + public void testHandleInvalidXml() throws Exception { + httpRequest.setMethod(HttpTransportConstants.METHOD_POST); + httpRequest.setContent(REQUEST.getBytes("UTF-8")); + httpRequest.setContentType("text/xml; charset=\"utf-8\""); + httpRequest.setCharacterEncoding("UTF-8"); + expect(factoryMock.createWebServiceMessage(isA(InputStream.class))).andThrow(new InvalidXmlException(null, null)); + + replayMockControls(); + + WebServiceMessageReceiver endpoint = new WebServiceMessageReceiver() { + + public void receive(MessageContext messageContext) throws Exception { + } + }; + + adapter.handle(httpRequest, httpResponse, endpoint); + Assert.assertEquals("No 400 returned", HttpServletResponse.SC_BAD_REQUEST, httpResponse.getStatus()); + + verifyMockControls(); + } + private void replayMockControls() { replay(factoryMock, requestMock, responseMock); } diff --git a/core/src/test/resources/org/springframework/ws/soap/soap11/soap11-ill-formed.xml b/core/src/test/resources/org/springframework/ws/soap/soap11/soap11-ill-formed.xml new file mode 100644 index 00000000..deabb4bc --- /dev/null +++ b/core/src/test/resources/org/springframework/ws/soap/soap11/soap11-ill-formed.xml @@ -0,0 +1,8 @@ + + + + DIS + + + \ No newline at end of file diff --git a/core/src/test/resources/org/springframework/ws/soap/soap12/soap12-ill-formed.xml b/core/src/test/resources/org/springframework/ws/soap/soap12/soap12-ill-formed.xml new file mode 100644 index 00000000..0595b746 --- /dev/null +++ b/core/src/test/resources/org/springframework/ws/soap/soap12/soap12-ill-formed.xml @@ -0,0 +1,7 @@ + + + + Pick up Mary at school at 2pm + + + \ No newline at end of file