SWS-544 - Added XSD validation

This commit is contained in:
Arjen Poutsma
2010-07-22 08:30:09 +00:00
parent d3a1a72163
commit 0a08364dfc
5 changed files with 245 additions and 1 deletions

View File

@@ -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));
}
}
}

View File

@@ -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.
*

View File

@@ -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(
"<test xmlns=\"http://www.example.org/schema\"><number>0</number><text>text</text></test>"));
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(
"<test xmlns=\"http://www.example.org/schema\"><number>a</number><text>text</text></test>"));
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(
"<test xmlns=\"http://www.example.org/schema\"><number>0</number><text>text</text></test>"));
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(
"<test xmlns=\"http://www.example.org/schema\"><number>a</number><text>text</text></test>"));
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(
"<test xmlns=\"http://www.example.org/schema\"><number>a</number><text>text</text></test>"));
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(
"<test xmlns=\"http://www.example.org/schema\"><number>a</number><text>text</text></test>"));
XmlValidator validator = XmlValidatorFactory.createValidator(schema1, XmlValidatorFactory.SCHEMA_W3C_XML);
RequestMatcher requestMatcher = new SchemaValidatingRequestMatcher(validator);
replay(message);
requestMatcher.match(null, message);
verify(message);
}
}

View File

@@ -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("<request xmlns='http://example.com'/>");
@@ -166,5 +168,28 @@ public class WebServiceMockTest {
template.sendSourceAndReceiveToResult(request, new StringResult());
}
@Test
public void xsdMatch() throws Exception {
Resource schema = new ByteArrayResource(
"<schema xmlns=\"http://www.w3.org/2001/XMLSchema\" targetNamespace=\"http://example.com\" elementFormDefault=\"qualified\"><element name=\"request\"/></schema>".getBytes());
expect(validPayload(schema));
StringResult result = new StringResult();
String actual = "<request xmlns='http://example.com'/>";
template.sendSourceAndReceiveToResult(new StringSource(actual), result);
}
@Test(expected = AssertionError.class)
public void xsdNonMatch() throws Exception {
Resource schema = new ByteArrayResource(
"<schema xmlns=\"http://www.w3.org/2001/XMLSchema\" targetNamespace=\"http://example.com\" elementFormDefault=\"qualified\"><element name=\"request\"/></schema>".getBytes());
expect(validPayload(schema));
StringResult result = new StringResult();
String actual = "<request2 xmlns='http://example.com'/>";
template.sendSourceAndReceiveToResult(new StringSource(actual), result);
}
}

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/schema" xmlns:tns="http://www.example.org/schema" elementFormDefault="qualified">
<element name="test" type="tns:testMessage"/>
<complexType name="testMessage">
<sequence>
<element name="number" type="int"/>
<element name="text" type="string" minOccurs="0"/>
</sequence>
</complexType>
</schema>