Skip to content

Commit 0a08364

Browse files
committed
SWS-544 - Added XSD validation
1 parent d3a1a72 commit 0a08364

File tree

5 files changed

+245
-1
lines changed

5 files changed

+245
-1
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Copyright 2005-2010 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.ws.mock.client;
18+
19+
import java.io.IOException;
20+
import java.net.URI;
21+
import java.util.Arrays;
22+
23+
import org.springframework.util.Assert;
24+
import org.springframework.util.ObjectUtils;
25+
import org.springframework.ws.WebServiceMessage;
26+
import org.springframework.xml.validation.XmlValidator;
27+
28+
import org.xml.sax.SAXParseException;
29+
30+
/**
31+
* Uses the {@link XmlValidator} to validate request payload.
32+
*
33+
* @author Lukas Krecan
34+
* @since 2.0
35+
*/
36+
class SchemaValidatingRequestMatcher implements RequestMatcher {
37+
38+
private final XmlValidator xmlValidator;
39+
40+
public SchemaValidatingRequestMatcher(XmlValidator xmlValidator) {
41+
Assert.notNull(xmlValidator, "XmlValidator has to be set");
42+
this.xmlValidator = xmlValidator;
43+
}
44+
45+
public void match(URI uri, WebServiceMessage request) throws IOException, AssertionError {
46+
SAXParseException[] exceptions = xmlValidator.validate(request.getPayloadSource());
47+
if (!ObjectUtils.isEmpty(exceptions)) {
48+
throw new AssertionError("XML is not valid: " + Arrays.toString(exceptions));
49+
}
50+
}
51+
}

test/src/main/java/org/springframework/ws/mock/client/WebServiceMock.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
import org.springframework.util.Assert;
2727
import org.springframework.ws.client.core.WebServiceTemplate;
2828
import org.springframework.xml.transform.ResourceSource;
29+
import org.springframework.xml.validation.XmlValidator;
30+
import org.springframework.xml.validation.XmlValidatorFactory;
2931

3032
/**
3133
* @author Arjen Poutsma
@@ -84,6 +86,27 @@ public static RequestMatcher payload(Resource payload) {
8486
return new PayloadDiffMatcher(createResourceSource(payload));
8587
}
8688

89+
/**
90+
* Expects the payload to validate against the given XSD schema(s).
91+
*
92+
* @param schema the schema
93+
* @param furtherSchemas further schemas, if necessary
94+
* @return the request matcher
95+
*/
96+
public static RequestMatcher validPayload(Resource schema, Resource... furtherSchemas) {
97+
try {
98+
Resource[] joinedSchemas = new Resource[furtherSchemas.length + 1];
99+
joinedSchemas[0] = schema;
100+
System.arraycopy(furtherSchemas, 0, joinedSchemas, 1, furtherSchemas.length);
101+
XmlValidator validator =
102+
XmlValidatorFactory.createValidator(joinedSchemas, XmlValidatorFactory.SCHEMA_W3C_XML);
103+
return new SchemaValidatingRequestMatcher(validator);
104+
}
105+
catch (IOException ex) {
106+
throw new IllegalArgumentException("Schema(s) could not be opened", ex);
107+
}
108+
}
109+
87110
/**
88111
* Expects the given SOAP header in the outgoing message.
89112
*
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
/*
2+
* Copyright 2005-2010 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.ws.mock.client;
18+
19+
import java.io.IOException;
20+
21+
import org.springframework.core.io.ByteArrayResource;
22+
import org.springframework.core.io.ClassPathResource;
23+
import org.springframework.core.io.Resource;
24+
import org.springframework.ws.WebServiceMessage;
25+
import org.springframework.xml.transform.StringSource;
26+
import org.springframework.xml.validation.XmlValidator;
27+
import org.springframework.xml.validation.XmlValidatorFactory;
28+
29+
import org.junit.Before;
30+
import org.junit.Test;
31+
32+
import static org.easymock.EasyMock.*;
33+
34+
public class SchemaValidatingRequestMatcherTest {
35+
36+
private Resource schema2;
37+
38+
private Resource schema1;
39+
40+
private WebServiceMessage message;
41+
42+
@Before
43+
public void setUp() {
44+
message = createMock(WebServiceMessage.class);
45+
schema1 = new ClassPathResource("schemaValidatingRequestMatcherTest.xsd", SchemaValidatingRequestMatcherTest.class);
46+
schema2 = new ByteArrayResource("".getBytes());
47+
}
48+
49+
@Test
50+
public void singleSchemaMatch() throws IOException, AssertionError {
51+
expect(message.getPayloadSource()).andReturn(new StringSource(
52+
"<test xmlns=\"http://www.example.org/schema\"><number>0</number><text>text</text></test>"));
53+
54+
RequestMatcher requestMatcher = WebServiceMock.validPayload(schema1);
55+
56+
replay(message);
57+
58+
requestMatcher.match(null, message);
59+
60+
verify(message);
61+
}
62+
63+
@Test(expected = AssertionError.class)
64+
public void singleSchemaNonMatch() throws IOException, AssertionError {
65+
expect(message.getPayloadSource()).andReturn(new StringSource(
66+
"<test xmlns=\"http://www.example.org/schema\"><number>a</number><text>text</text></test>"));
67+
68+
RequestMatcher requestMatcher = WebServiceMock.validPayload(schema1);
69+
70+
replay(message);
71+
72+
requestMatcher.match(null, message);
73+
74+
verify(message);
75+
}
76+
77+
@Test
78+
public void multipleSchemaMatch() throws IOException, AssertionError {
79+
expect(message.getPayloadSource()).andReturn(new StringSource(
80+
"<test xmlns=\"http://www.example.org/schema\"><number>0</number><text>text</text></test>"));
81+
82+
RequestMatcher requestMatcher = WebServiceMock.validPayload(schema1, schema2);
83+
84+
replay(message);
85+
86+
requestMatcher.match(null, message);
87+
88+
verify(message);
89+
}
90+
91+
@Test(expected = AssertionError.class)
92+
public void multipleSchemaNotOk() throws IOException, AssertionError {
93+
expect(message.getPayloadSource()).andReturn(new StringSource(
94+
"<test xmlns=\"http://www.example.org/schema\"><number>a</number><text>text</text></test>"));
95+
96+
RequestMatcher requestMatcher = WebServiceMock.validPayload(schema1, schema2);
97+
98+
replay(message);
99+
100+
requestMatcher.match(null, message);
101+
102+
verify(message);
103+
}
104+
105+
@Test(expected = AssertionError.class)
106+
public void multipleSchemaDifferentOrderNotOk() throws IOException, AssertionError {
107+
expect(message.getPayloadSource()).andReturn(new StringSource(
108+
"<test xmlns=\"http://www.example.org/schema\"><number>a</number><text>text</text></test>"));
109+
110+
RequestMatcher requestMatcher = WebServiceMock.validPayload(schema2, schema1);
111+
112+
replay(message);
113+
114+
requestMatcher.match(null, message);
115+
116+
verify(message);
117+
}
118+
119+
@Test(expected = AssertionError.class)
120+
public void xmlValidatorNotOk() throws IOException, AssertionError {
121+
expect(message.getPayloadSource()).andReturn(new StringSource(
122+
"<test xmlns=\"http://www.example.org/schema\"><number>a</number><text>text</text></test>"));
123+
124+
XmlValidator validator = XmlValidatorFactory.createValidator(schema1, XmlValidatorFactory.SCHEMA_W3C_XML);
125+
RequestMatcher requestMatcher = new SchemaValidatingRequestMatcher(validator);
126+
127+
replay(message);
128+
129+
requestMatcher.match(null, message);
130+
131+
verify(message);
132+
}
133+
}

test/src/test/java/org/springframework/ws/mock/client/WebServiceMockTest.java

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
import javax.xml.transform.Source;
2323
import javax.xml.transform.TransformerException;
2424

25+
import org.springframework.core.io.ByteArrayResource;
26+
import org.springframework.core.io.Resource;
2527
import org.springframework.ws.WebServiceMessage;
2628
import org.springframework.ws.client.core.WebServiceMessageCallback;
2729
import org.springframework.ws.client.core.WebServiceTemplate;
@@ -154,7 +156,7 @@ public void verifyThreadLocalCleanUp() throws Exception {
154156
template.sendSourceAndReceiveToResult(request, new StringResult());
155157
assertNull(MockWebServiceMessageSenderHolder.get());
156158
}
157-
159+
158160
@Test(expected = AssertionError.class)
159161
public void unexpectedConnection() throws Exception {
160162
Source request = new StringSource("<request xmlns='http://example.com'/>");
@@ -166,5 +168,28 @@ public void unexpectedConnection() throws Exception {
166168
template.sendSourceAndReceiveToResult(request, new StringResult());
167169
}
168170

171+
@Test
172+
public void xsdMatch() throws Exception {
173+
Resource schema = new ByteArrayResource(
174+
"<schema xmlns=\"http://www.w3.org/2001/XMLSchema\" targetNamespace=\"http://example.com\" elementFormDefault=\"qualified\"><element name=\"request\"/></schema>".getBytes());
175+
176+
expect(validPayload(schema));
177+
178+
StringResult result = new StringResult();
179+
String actual = "<request xmlns='http://example.com'/>";
180+
template.sendSourceAndReceiveToResult(new StringSource(actual), result);
181+
}
182+
183+
@Test(expected = AssertionError.class)
184+
public void xsdNonMatch() throws Exception {
185+
Resource schema = new ByteArrayResource(
186+
"<schema xmlns=\"http://www.w3.org/2001/XMLSchema\" targetNamespace=\"http://example.com\" elementFormDefault=\"qualified\"><element name=\"request\"/></schema>".getBytes());
187+
188+
expect(validPayload(schema));
189+
190+
StringResult result = new StringResult();
191+
String actual = "<request2 xmlns='http://example.com'/>";
192+
template.sendSourceAndReceiveToResult(new StringSource(actual), result);
193+
}
169194

170195
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/schema" xmlns:tns="http://www.example.org/schema" elementFormDefault="qualified">
3+
4+
<element name="test" type="tns:testMessage"/>
5+
6+
<complexType name="testMessage">
7+
<sequence>
8+
<element name="number" type="int"/>
9+
<element name="text" type="string" minOccurs="0"/>
10+
</sequence>
11+
</complexType>
12+
</schema>

0 commit comments

Comments
 (0)