1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.ws.soap.server.endpoint.interceptor;
18
19 import java.io.ByteArrayOutputStream;
20 import java.io.InputStream;
21 import java.util.Locale;
22 import javax.xml.XMLConstants;
23 import javax.xml.soap.MessageFactory;
24 import javax.xml.soap.SOAPConstants;
25 import javax.xml.soap.SOAPMessage;
26 import javax.xml.transform.Transformer;
27 import javax.xml.transform.TransformerFactory;
28 import javax.xml.transform.stream.StreamSource;
29
30 import org.springframework.core.io.ClassPathResource;
31 import org.springframework.core.io.Resource;
32 import org.springframework.ws.MockWebServiceMessage;
33 import org.springframework.ws.MockWebServiceMessageFactory;
34 import org.springframework.ws.WebServiceMessage;
35 import org.springframework.ws.context.DefaultMessageContext;
36 import org.springframework.ws.context.MessageContext;
37 import org.springframework.ws.soap.SoapMessage;
38 import org.springframework.ws.soap.SoapVersion;
39 import org.springframework.ws.soap.axiom.AxiomSoapMessageFactory;
40 import org.springframework.ws.soap.saaj.SaajSoapMessage;
41 import org.springframework.ws.soap.saaj.SaajSoapMessageFactory;
42 import org.springframework.ws.soap.saaj.support.SaajUtils;
43 import org.springframework.ws.soap.soap11.Soap11Fault;
44 import org.springframework.ws.soap.soap12.Soap12Fault;
45 import org.springframework.ws.transport.MockTransportInputStream;
46 import org.springframework.ws.transport.TransportInputStream;
47 import org.springframework.xml.validation.ValidationErrorHandler;
48 import org.springframework.xml.xsd.SimpleXsdSchema;
49
50 import org.junit.Assert;
51 import org.junit.Before;
52 import org.junit.Test;
53 import org.xml.sax.SAXException;
54 import org.xml.sax.SAXParseException;
55 import org.xml.sax.helpers.LocatorImpl;
56
57 import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual;
58
59 public class PayloadValidatingInterceptorTest {
60
61 private PayloadValidatingInterceptor interceptor;
62
63 private MessageContext context;
64
65 private SaajSoapMessageFactory soap11Factory;
66
67 private SaajSoapMessageFactory soap12Factory;
68
69 private Transformer transformer;
70
71 private static final String INVALID_MESSAGE = "invalidMessage.xml";
72
73 private static final String SCHEMA = "schema.xsd";
74
75 private static final String VALID_MESSAGE = "validMessage.xml";
76
77 private static final String PRODUCT_SCHEMA = "productSchema.xsd";
78
79 private static final String SIZE_SCHEMA = "sizeSchema.xsd";
80
81 private static final String VALID_SOAP_MESSAGE = "validSoapMessage.xml";
82
83 private static final String SCHEMA2 = "schema2.xsd";
84
85 @Before
86 public void setUp() throws Exception {
87 interceptor = new PayloadValidatingInterceptor();
88 interceptor.setSchema(new ClassPathResource(SCHEMA, getClass()));
89 interceptor.setValidateRequest(true);
90 interceptor.setValidateResponse(true);
91 interceptor.afterPropertiesSet();
92
93 soap11Factory = new SaajSoapMessageFactory(MessageFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL));
94 soap12Factory = new SaajSoapMessageFactory(MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL));
95 transformer = TransformerFactory.newInstance().newTransformer();
96 }
97
98 @Test
99 public void testHandleInvalidRequestSoap11() throws Exception {
100 SoapMessage invalidMessage = soap11Factory.createWebServiceMessage();
101 InputStream inputStream = getClass().getResourceAsStream(INVALID_MESSAGE);
102 transformer.transform(new StreamSource(inputStream), invalidMessage.getPayloadResult());
103 context = new DefaultMessageContext(invalidMessage, soap11Factory);
104
105 boolean result = interceptor.handleRequest(context, null);
106 Assert.assertFalse("Invalid response from interceptor", result);
107 Assert.assertTrue("Context has no response", context.hasResponse());
108 SoapMessage response = (SoapMessage) context.getResponse();
109 Assert.assertTrue("Response has no fault", response.getSoapBody().hasFault());
110 Soap11Fault fault = (Soap11Fault) response.getSoapBody().getFault();
111 Assert.assertEquals("Invalid fault code on fault", SoapVersion.SOAP_11.getClientOrSenderFaultName(),
112 fault.getFaultCode());
113 Assert.assertEquals("Invalid fault string on fault", PayloadValidatingInterceptor.DEFAULT_FAULTSTRING_OR_REASON,
114 fault.getFaultStringOrReason());
115 Assert.assertNotNull("No Detail on fault", fault.getFaultDetail());
116 }
117
118 @Test
119 public void testHandleInvalidRequestSoap12() throws Exception {
120 SoapMessage invalidMessage = soap12Factory.createWebServiceMessage();
121 InputStream inputStream = getClass().getResourceAsStream(INVALID_MESSAGE);
122 transformer.transform(new StreamSource(inputStream), invalidMessage.getPayloadResult());
123 context = new DefaultMessageContext(invalidMessage, soap12Factory);
124
125 boolean result = interceptor.handleRequest(context, null);
126 Assert.assertFalse("Invalid response from interceptor", result);
127 Assert.assertTrue("Context has no response", context.hasResponse());
128 SoapMessage response = (SoapMessage) context.getResponse();
129 Assert.assertTrue("Response has no fault", response.getSoapBody().hasFault());
130 Soap12Fault fault = (Soap12Fault) response.getSoapBody().getFault();
131 Assert.assertEquals("Invalid fault code on fault", SoapVersion.SOAP_12.getClientOrSenderFaultName(),
132 fault.getFaultCode());
133 Assert.assertEquals("Invalid fault string on fault", PayloadValidatingInterceptor.DEFAULT_FAULTSTRING_OR_REASON,
134 fault.getFaultReasonText(Locale.ENGLISH));
135 Assert.assertNotNull("No Detail on fault", fault.getFaultDetail());
136 }
137
138 @Test
139 public void testHandleInvalidRequestOverridenProperties() throws Exception {
140 String faultString = "fout";
141 Locale locale = new Locale("nl");
142 interceptor.setFaultStringOrReason(faultString);
143 interceptor.setFaultStringOrReasonLocale(locale);
144 interceptor.setAddValidationErrorDetail(false);
145
146 SoapMessage invalidMessage = (SoapMessage) soap11Factory.createWebServiceMessage();
147 InputStream inputStream = getClass().getResourceAsStream(INVALID_MESSAGE);
148 transformer.transform(new StreamSource(inputStream), invalidMessage.getPayloadResult());
149 context = new DefaultMessageContext(invalidMessage, soap11Factory);
150
151 boolean result = interceptor.handleRequest(context, null);
152 Assert.assertFalse("Invalid response from interceptor", result);
153 Assert.assertTrue("Context has no response", context.hasResponse());
154 SoapMessage response = (SoapMessage) context.getResponse();
155 Assert.assertTrue("Response has no fault", response.getSoapBody().hasFault());
156 Soap11Fault fault = (Soap11Fault) response.getSoapBody().getFault();
157 Assert.assertEquals("Invalid fault code on fault", SoapVersion.SOAP_11.getClientOrSenderFaultName(),
158 fault.getFaultCode());
159 Assert.assertEquals("Invalid fault string on fault", faultString, fault.getFaultStringOrReason());
160 Assert.assertEquals("Invalid fault string locale on fault", locale, fault.getFaultStringLocale());
161 Assert.assertNull("Detail on fault", fault.getFaultDetail());
162 }
163
164 @Test
165 public void testHandlerInvalidRequest() throws Exception {
166 MockWebServiceMessage request = new MockWebServiceMessage();
167 request.setPayload(new ClassPathResource(INVALID_MESSAGE, getClass()));
168 context = new DefaultMessageContext(request, new MockWebServiceMessageFactory());
169 boolean result = interceptor.handleRequest(context, null);
170 Assert.assertFalse("Invalid response from interceptor", result);
171 }
172
173 @Test
174 public void testHandleValidRequest() throws Exception {
175 MockWebServiceMessage request = new MockWebServiceMessage();
176 request.setPayload(new ClassPathResource(VALID_MESSAGE, getClass()));
177 context = new DefaultMessageContext(request, new MockWebServiceMessageFactory());
178 boolean result = interceptor.handleRequest(context, null);
179 Assert.assertTrue("Invalid response from interceptor", result);
180 Assert.assertFalse("Response set", context.hasResponse());
181 }
182
183 @Test
184 public void testHandleInvalidResponse() throws Exception {
185 MockWebServiceMessage request = new MockWebServiceMessage();
186 context = new DefaultMessageContext(request, new MockWebServiceMessageFactory());
187 MockWebServiceMessage response = (MockWebServiceMessage) context.getResponse();
188 response.setPayload(new ClassPathResource(INVALID_MESSAGE, getClass()));
189 boolean result = interceptor.handleResponse(context, null);
190 Assert.assertFalse("Invalid response from interceptor", result);
191 }
192
193 @Test
194 public void testHandleValidResponse() throws Exception {
195 MockWebServiceMessage request = new MockWebServiceMessage();
196 context = new DefaultMessageContext(request, new MockWebServiceMessageFactory());
197 MockWebServiceMessage response = (MockWebServiceMessage) context.getResponse();
198 response.setPayload(new ClassPathResource(VALID_MESSAGE, getClass()));
199 boolean result = interceptor.handleResponse(context, null);
200 Assert.assertTrue("Invalid response from interceptor", result);
201 }
202
203 @Test
204 public void testNamespacesInType() throws Exception {
205
206
207 String previousSchemaFactory =
208 System.getProperty("javax.xml.validation.SchemaFactory:" + XMLConstants.W3C_XML_SCHEMA_NS_URI, "");
209 System.setProperty("javax.xml.validation.SchemaFactory:" + XMLConstants.W3C_XML_SCHEMA_NS_URI,
210 "org.apache.xerces.jaxp.validation.XMLSchemaFactory");
211 try {
212 PayloadValidatingInterceptor interceptor = new PayloadValidatingInterceptor();
213 interceptor.setSchema(new ClassPathResource(SCHEMA2, PayloadValidatingInterceptorTest.class));
214 interceptor.afterPropertiesSet();
215 MessageFactory messageFactory = MessageFactory.newInstance();
216 SOAPMessage saajMessage =
217 SaajUtils.loadMessage(new ClassPathResource(VALID_SOAP_MESSAGE, getClass()), messageFactory);
218 context = new DefaultMessageContext(new SaajSoapMessage(saajMessage),
219 new SaajSoapMessageFactory(messageFactory));
220
221 boolean result = interceptor.handleRequest(context, null);
222 Assert.assertTrue("Invalid response from interceptor", result);
223 Assert.assertFalse("Response set", context.hasResponse());
224 }
225 finally {
226
227 System.setProperty("javax.xml.validation.SchemaFactory:" + XMLConstants.W3C_XML_SCHEMA_NS_URI,
228 previousSchemaFactory);
229 }
230 }
231
232 @Test
233 public void testNonExistingSchema() throws Exception {
234 try {
235 interceptor.setSchema(new ClassPathResource("invalid"));
236 interceptor.afterPropertiesSet();
237 Assert.fail("IllegalArgumentException expected");
238 }
239 catch (IllegalArgumentException ex) {
240
241 }
242 }
243
244 @Test
245 public void testHandlerInvalidRequestMultipleSchemas() throws Exception {
246 interceptor.setSchemas(new Resource[]{new ClassPathResource(PRODUCT_SCHEMA, getClass()),
247 new ClassPathResource(SIZE_SCHEMA, getClass())});
248 interceptor.afterPropertiesSet();
249 MockWebServiceMessage request = new MockWebServiceMessage(new ClassPathResource(INVALID_MESSAGE, getClass()));
250 context = new DefaultMessageContext(request, new MockWebServiceMessageFactory());
251 boolean result = interceptor.handleRequest(context, null);
252 Assert.assertFalse("Invalid response from interceptor", result);
253 }
254
255 @Test
256 public void testHandleValidRequestMultipleSchemas() throws Exception {
257 interceptor.setSchemas(new Resource[]{new ClassPathResource(PRODUCT_SCHEMA, getClass()),
258 new ClassPathResource(SIZE_SCHEMA, getClass())});
259 interceptor.afterPropertiesSet();
260 MockWebServiceMessage request = new MockWebServiceMessage(new ClassPathResource(VALID_MESSAGE, getClass()));
261 context = new DefaultMessageContext(request, new MockWebServiceMessageFactory());
262
263 boolean result = interceptor.handleRequest(context, null);
264 Assert.assertTrue("Invalid response from interceptor", result);
265 Assert.assertFalse("Response set", context.hasResponse());
266 }
267
268 @Test
269 public void testHandleInvalidResponseMultipleSchemas() throws Exception {
270 interceptor.setSchemas(new Resource[]{new ClassPathResource(PRODUCT_SCHEMA, getClass()),
271 new ClassPathResource(SIZE_SCHEMA, getClass())});
272 interceptor.afterPropertiesSet();
273 MockWebServiceMessage request = new MockWebServiceMessage();
274 context = new DefaultMessageContext(request, new MockWebServiceMessageFactory());
275 MockWebServiceMessage response = (MockWebServiceMessage) context.getResponse();
276 response.setPayload(new ClassPathResource(INVALID_MESSAGE, getClass()));
277 boolean result = interceptor.handleResponse(context, null);
278 Assert.assertFalse("Invalid response from interceptor", result);
279 }
280
281 @Test
282 public void testHandleValidResponseMultipleSchemas() throws Exception {
283 interceptor.setSchemas(new Resource[]{new ClassPathResource(PRODUCT_SCHEMA, getClass()),
284 new ClassPathResource(SIZE_SCHEMA, getClass())});
285 interceptor.afterPropertiesSet();
286 MockWebServiceMessage request = new MockWebServiceMessage();
287 context = new DefaultMessageContext(request, new MockWebServiceMessageFactory());
288 MockWebServiceMessage response = (MockWebServiceMessage) context.getResponse();
289 response.setPayload(new ClassPathResource(VALID_MESSAGE, getClass()));
290 boolean result = interceptor.handleResponse(context, null);
291 Assert.assertTrue("Invalid response from interceptor", result);
292 }
293
294 @Test
295 public void testCreateRequestValidationFaultAxiom() throws Exception {
296 LocatorImpl locator = new LocatorImpl();
297 locator.setLineNumber(0);
298 locator.setColumnNumber(0);
299 SAXParseException[] exceptions = new SAXParseException[]{new SAXParseException("Message 1", locator),
300 new SAXParseException("Message 2", locator),};
301 MessageContext messageContext = new DefaultMessageContext(new AxiomSoapMessageFactory());
302 interceptor.handleRequestValidationErrors(messageContext, exceptions);
303 ByteArrayOutputStream os = new ByteArrayOutputStream();
304 messageContext.getResponse().writeTo(os);
305 assertXMLEqual(
306 "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\">" + "<soapenv:Body>" +
307 "<soapenv:Fault>" + "<faultcode>soapenv:Client</faultcode>" +
308 "<faultstring xml:lang='en'>Validation error</faultstring>" + "<detail>" +
309 "<spring-ws:ValidationError xmlns:spring-ws=\"http://springframework.org/spring-ws\">Message 1</spring-ws:ValidationError>" +
310 "<spring-ws:ValidationError xmlns:spring-ws=\"http://springframework.org/spring-ws\">Message 2</spring-ws:ValidationError>" +
311 "</detail>" + "</soapenv:Fault>" + "</soapenv:Body>" + "</soapenv:Envelope>", os.toString());
312
313 }
314
315 @Test
316 public void testXsdSchema() throws Exception {
317 PayloadValidatingInterceptor interceptor = new PayloadValidatingInterceptor();
318 SimpleXsdSchema schema = new SimpleXsdSchema(new ClassPathResource(SCHEMA, getClass()));
319 schema.afterPropertiesSet();
320 interceptor.setXsdSchema(schema);
321 interceptor.setValidateRequest(true);
322 interceptor.setValidateResponse(true);
323 interceptor.afterPropertiesSet();
324 MockWebServiceMessage request = new MockWebServiceMessage();
325 request.setPayload(new ClassPathResource(VALID_MESSAGE, getClass()));
326 context = new DefaultMessageContext(request, new MockWebServiceMessageFactory());
327 boolean result = interceptor.handleRequest(context, null);
328 Assert.assertTrue("Invalid response from interceptor", result);
329 Assert.assertFalse("Response set", context.hasResponse());
330 }
331
332 @Test
333 public void testAxiom() throws Exception {
334 AxiomSoapMessageFactory messageFactory = new AxiomSoapMessageFactory();
335 messageFactory.setPayloadCaching(true);
336 messageFactory.afterPropertiesSet();
337
338 PayloadValidatingInterceptor interceptor = new PayloadValidatingInterceptor();
339 interceptor.setSchema(new ClassPathResource("codexws.xsd", getClass()));
340 interceptor.afterPropertiesSet();
341
342 Resource resource = new ClassPathResource("axiom.xml", getClass());
343 TransportInputStream tis = new MockTransportInputStream(resource.getInputStream());
344 WebServiceMessage message = messageFactory.createWebServiceMessage(tis);
345 MessageContext context = new DefaultMessageContext(message, messageFactory);
346 boolean result = interceptor.handleRequest(context, null);
347 Assert.assertTrue("Invalid response from interceptor", result);
348
349 }
350
351 @Test
352 public void testMultipleNamespacesAxiom() throws Exception {
353 AxiomSoapMessageFactory messageFactory = new AxiomSoapMessageFactory();
354 messageFactory.setPayloadCaching(true);
355 messageFactory.afterPropertiesSet();
356
357 PayloadValidatingInterceptor interceptor = new PayloadValidatingInterceptor();
358 interceptor.setSchema(new ClassPathResource("multipleNamespaces.xsd", getClass()));
359 interceptor.afterPropertiesSet();
360
361 Resource resource = new ClassPathResource("multipleNamespaces.xml", getClass());
362 TransportInputStream tis = new MockTransportInputStream(resource.getInputStream());
363 WebServiceMessage message = messageFactory.createWebServiceMessage(tis);
364 MessageContext context = new DefaultMessageContext(message, messageFactory);
365 boolean result = interceptor.handleRequest(context, null);
366 Assert.assertTrue("Invalid response from interceptor", result);
367
368 }
369
370 @Test
371 public void customErrorHandler() throws Exception {
372 ValidationErrorHandler errorHandler = new ValidationErrorHandler() {
373 public SAXParseException[] getErrors() {
374 return new SAXParseException[0];
375 }
376
377 public void warning(SAXParseException exception) throws SAXException {
378 }
379
380 public void error(SAXParseException exception) throws SAXException {
381 }
382
383 public void fatalError(SAXParseException exception) throws SAXException {
384 }
385 };
386 interceptor.setErrorHandler(errorHandler);
387 SoapMessage invalidMessage = soap11Factory.createWebServiceMessage();
388 InputStream inputStream = getClass().getResourceAsStream(INVALID_MESSAGE);
389 transformer.transform(new StreamSource(inputStream), invalidMessage.getPayloadResult());
390 context = new DefaultMessageContext(invalidMessage, soap11Factory);
391
392 boolean result = interceptor.handleRequest(context, null);
393 Assert.assertTrue("Invalid response from interceptor", result);
394 Assert.assertFalse("Context has response", context.hasResponse());
395 }
396
397 }