From 0a08364dfcd3223752295e459bbfc6e9b2512dfb Mon Sep 17 00:00:00 2001 From: Arjen Poutsma Date: Thu, 22 Jul 2010 08:30:09 +0000 Subject: [PATCH] SWS-544 - Added XSD validation --- .../SchemaValidatingRequestMatcher.java | 51 +++++++ .../ws/mock/client/WebServiceMock.java | 23 +++ .../SchemaValidatingRequestMatcherTest.java | 133 ++++++++++++++++++ .../ws/mock/client/WebServiceMockTest.java | 27 +++- .../schemaValidatingRequestMatcherTest.xsd | 12 ++ 5 files changed, 245 insertions(+), 1 deletion(-) create mode 100644 test/src/main/java/org/springframework/ws/mock/client/SchemaValidatingRequestMatcher.java create mode 100644 test/src/test/java/org/springframework/ws/mock/client/SchemaValidatingRequestMatcherTest.java create mode 100644 test/src/test/resources/org/springframework/ws/mock/client/schemaValidatingRequestMatcherTest.xsd diff --git a/test/src/main/java/org/springframework/ws/mock/client/SchemaValidatingRequestMatcher.java b/test/src/main/java/org/springframework/ws/mock/client/SchemaValidatingRequestMatcher.java new file mode 100644 index 00000000..795e6f31 --- /dev/null +++ b/test/src/main/java/org/springframework/ws/mock/client/SchemaValidatingRequestMatcher.java @@ -0,0 +1,51 @@ +/* + * 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.mock.client; + +import java.io.IOException; +import java.net.URI; +import java.util.Arrays; + +import org.springframework.util.Assert; +import org.springframework.util.ObjectUtils; +import org.springframework.ws.WebServiceMessage; +import org.springframework.xml.validation.XmlValidator; + +import org.xml.sax.SAXParseException; + +/** + * Uses the {@link XmlValidator} to validate request payload. + * + * @author Lukas Krecan + * @since 2.0 + */ +class SchemaValidatingRequestMatcher implements RequestMatcher { + + private final XmlValidator xmlValidator; + + public SchemaValidatingRequestMatcher(XmlValidator xmlValidator) { + Assert.notNull(xmlValidator, "XmlValidator has to be set"); + this.xmlValidator = xmlValidator; + } + + public void match(URI uri, WebServiceMessage request) throws IOException, AssertionError { + SAXParseException[] exceptions = xmlValidator.validate(request.getPayloadSource()); + if (!ObjectUtils.isEmpty(exceptions)) { + throw new AssertionError("XML is not valid: " + Arrays.toString(exceptions)); + } + } +} diff --git a/test/src/main/java/org/springframework/ws/mock/client/WebServiceMock.java b/test/src/main/java/org/springframework/ws/mock/client/WebServiceMock.java index 9735265d..1cd95fb4 100644 --- a/test/src/main/java/org/springframework/ws/mock/client/WebServiceMock.java +++ b/test/src/main/java/org/springframework/ws/mock/client/WebServiceMock.java @@ -26,6 +26,8 @@ import org.springframework.core.io.Resource; import org.springframework.util.Assert; import org.springframework.ws.client.core.WebServiceTemplate; import org.springframework.xml.transform.ResourceSource; +import org.springframework.xml.validation.XmlValidator; +import org.springframework.xml.validation.XmlValidatorFactory; /** * @author Arjen Poutsma @@ -84,6 +86,27 @@ public abstract class WebServiceMock { return new PayloadDiffMatcher(createResourceSource(payload)); } + /** + * Expects the payload to validate against the given XSD schema(s). + * + * @param schema the schema + * @param furtherSchemas further schemas, if necessary + * @return the request matcher + */ + public static RequestMatcher validPayload(Resource schema, Resource... furtherSchemas) { + try { + Resource[] joinedSchemas = new Resource[furtherSchemas.length + 1]; + joinedSchemas[0] = schema; + System.arraycopy(furtherSchemas, 0, joinedSchemas, 1, furtherSchemas.length); + XmlValidator validator = + XmlValidatorFactory.createValidator(joinedSchemas, XmlValidatorFactory.SCHEMA_W3C_XML); + return new SchemaValidatingRequestMatcher(validator); + } + catch (IOException ex) { + throw new IllegalArgumentException("Schema(s) could not be opened", ex); + } + } + /** * Expects the given SOAP header in the outgoing message. * diff --git a/test/src/test/java/org/springframework/ws/mock/client/SchemaValidatingRequestMatcherTest.java b/test/src/test/java/org/springframework/ws/mock/client/SchemaValidatingRequestMatcherTest.java new file mode 100644 index 00000000..5d9eea33 --- /dev/null +++ b/test/src/test/java/org/springframework/ws/mock/client/SchemaValidatingRequestMatcherTest.java @@ -0,0 +1,133 @@ +/* + * 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.mock.client; + +import java.io.IOException; + +import org.springframework.core.io.ByteArrayResource; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; +import org.springframework.ws.WebServiceMessage; +import org.springframework.xml.transform.StringSource; +import org.springframework.xml.validation.XmlValidator; +import org.springframework.xml.validation.XmlValidatorFactory; + +import org.junit.Before; +import org.junit.Test; + +import static org.easymock.EasyMock.*; + +public class SchemaValidatingRequestMatcherTest { + + private Resource schema2; + + private Resource schema1; + + private WebServiceMessage message; + + @Before + public void setUp() { + message = createMock(WebServiceMessage.class); + schema1 = new ClassPathResource("schemaValidatingRequestMatcherTest.xsd", SchemaValidatingRequestMatcherTest.class); + schema2 = new ByteArrayResource("".getBytes()); + } + + @Test + public void singleSchemaMatch() throws IOException, AssertionError { + expect(message.getPayloadSource()).andReturn(new StringSource( + "0text")); + + RequestMatcher requestMatcher = WebServiceMock.validPayload(schema1); + + replay(message); + + requestMatcher.match(null, message); + + verify(message); + } + + @Test(expected = AssertionError.class) + public void singleSchemaNonMatch() throws IOException, AssertionError { + expect(message.getPayloadSource()).andReturn(new StringSource( + "atext")); + + RequestMatcher requestMatcher = WebServiceMock.validPayload(schema1); + + replay(message); + + requestMatcher.match(null, message); + + verify(message); + } + + @Test + public void multipleSchemaMatch() throws IOException, AssertionError { + expect(message.getPayloadSource()).andReturn(new StringSource( + "0text")); + + RequestMatcher requestMatcher = WebServiceMock.validPayload(schema1, schema2); + + replay(message); + + requestMatcher.match(null, message); + + verify(message); + } + + @Test(expected = AssertionError.class) + public void multipleSchemaNotOk() throws IOException, AssertionError { + expect(message.getPayloadSource()).andReturn(new StringSource( + "atext")); + + RequestMatcher requestMatcher = WebServiceMock.validPayload(schema1, schema2); + + replay(message); + + requestMatcher.match(null, message); + + verify(message); + } + + @Test(expected = AssertionError.class) + public void multipleSchemaDifferentOrderNotOk() throws IOException, AssertionError { + expect(message.getPayloadSource()).andReturn(new StringSource( + "atext")); + + RequestMatcher requestMatcher = WebServiceMock.validPayload(schema2, schema1); + + replay(message); + + requestMatcher.match(null, message); + + verify(message); + } + + @Test(expected = AssertionError.class) + public void xmlValidatorNotOk() throws IOException, AssertionError { + expect(message.getPayloadSource()).andReturn(new StringSource( + "atext")); + + XmlValidator validator = XmlValidatorFactory.createValidator(schema1, XmlValidatorFactory.SCHEMA_W3C_XML); + RequestMatcher requestMatcher = new SchemaValidatingRequestMatcher(validator); + + replay(message); + + requestMatcher.match(null, message); + + verify(message); + } +} diff --git a/test/src/test/java/org/springframework/ws/mock/client/WebServiceMockTest.java b/test/src/test/java/org/springframework/ws/mock/client/WebServiceMockTest.java index bd29dc9c..33544d9d 100644 --- a/test/src/test/java/org/springframework/ws/mock/client/WebServiceMockTest.java +++ b/test/src/test/java/org/springframework/ws/mock/client/WebServiceMockTest.java @@ -22,6 +22,8 @@ import javax.xml.namespace.QName; import javax.xml.transform.Source; import javax.xml.transform.TransformerException; +import org.springframework.core.io.ByteArrayResource; +import org.springframework.core.io.Resource; import org.springframework.ws.WebServiceMessage; import org.springframework.ws.client.core.WebServiceMessageCallback; import org.springframework.ws.client.core.WebServiceTemplate; @@ -154,7 +156,7 @@ public class WebServiceMockTest { template.sendSourceAndReceiveToResult(request, new StringResult()); assertNull(MockWebServiceMessageSenderHolder.get()); } - + @Test(expected = AssertionError.class) public void unexpectedConnection() throws Exception { Source request = new StringSource(""); @@ -166,5 +168,28 @@ public class WebServiceMockTest { template.sendSourceAndReceiveToResult(request, new StringResult()); } + @Test + public void xsdMatch() throws Exception { + Resource schema = new ByteArrayResource( + "".getBytes()); + + expect(validPayload(schema)); + + StringResult result = new StringResult(); + String actual = ""; + template.sendSourceAndReceiveToResult(new StringSource(actual), result); + } + + @Test(expected = AssertionError.class) + public void xsdNonMatch() throws Exception { + Resource schema = new ByteArrayResource( + "".getBytes()); + + expect(validPayload(schema)); + + StringResult result = new StringResult(); + String actual = ""; + template.sendSourceAndReceiveToResult(new StringSource(actual), result); + } } diff --git a/test/src/test/resources/org/springframework/ws/mock/client/schemaValidatingRequestMatcherTest.xsd b/test/src/test/resources/org/springframework/ws/mock/client/schemaValidatingRequestMatcherTest.xsd new file mode 100644 index 00000000..a0bc71eb --- /dev/null +++ b/test/src/test/resources/org/springframework/ws/mock/client/schemaValidatingRequestMatcherTest.xsd @@ -0,0 +1,12 @@ + + + + + + + + + + + +