1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.ws.client.support.interceptor;
18
19 import java.io.IOException;
20 import javax.xml.transform.Source;
21
22 import org.springframework.beans.factory.InitializingBean;
23 import org.springframework.core.io.Resource;
24 import org.springframework.util.Assert;
25 import org.springframework.util.ObjectUtils;
26 import org.springframework.util.StringUtils;
27 import org.springframework.ws.WebServiceMessage;
28 import org.springframework.ws.client.WebServiceClientException;
29 import org.springframework.ws.client.WebServiceIOException;
30 import org.springframework.ws.context.MessageContext;
31 import org.springframework.xml.transform.TransformerObjectSupport;
32 import org.springframework.xml.validation.XmlValidator;
33 import org.springframework.xml.validation.XmlValidatorFactory;
34 import org.springframework.xml.xsd.XsdSchema;
35 import org.springframework.xml.xsd.XsdSchemaCollection;
36
37 import org.xml.sax.SAXParseException;
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 public abstract class AbstractValidatingInterceptor extends TransformerObjectSupport
53 implements ClientInterceptor, InitializingBean {
54
55 private String schemaLanguage = XmlValidatorFactory.SCHEMA_W3C_XML;
56
57 private Resource[] schemas;
58
59 private boolean validateRequest = true;
60
61 private boolean validateResponse = false;
62
63 private XmlValidator validator;
64
65 public String getSchemaLanguage() {
66 return schemaLanguage;
67 }
68
69
70
71
72
73
74
75 public void setSchemaLanguage(String schemaLanguage) {
76 this.schemaLanguage = schemaLanguage;
77 }
78
79
80 public Resource[] getSchemas() {
81 return schemas;
82 }
83
84
85
86
87
88
89 public void setSchema(Resource schema) {
90 setSchemas(new Resource[]{schema});
91 }
92
93
94
95
96
97
98 public void setSchemas(Resource[] schemas) {
99 Assert.notEmpty(schemas, "schemas must not be empty or null");
100 for (Resource schema : schemas) {
101 Assert.notNull(schema, "schema must not be null");
102 Assert.isTrue(schema.exists(), "schema \"" + schema + "\" does not exit");
103 }
104 this.schemas = schemas;
105 }
106
107
108
109
110
111
112
113
114
115 public void setXsdSchema(XsdSchema schema) throws IOException {
116 this.validator = schema.createValidator();
117 }
118
119
120
121
122
123
124
125
126
127 public void setXsdSchemaCollection(XsdSchemaCollection schemaCollection) throws IOException {
128 this.validator = schemaCollection.createValidator();
129 }
130
131
132 public void setValidateRequest(boolean validateRequest) {
133 this.validateRequest = validateRequest;
134 }
135
136
137 public void setValidateResponse(boolean validateResponse) {
138 this.validateResponse = validateResponse;
139 }
140
141 public void afterPropertiesSet() throws Exception {
142 if (validator == null && !ObjectUtils.isEmpty(schemas)) {
143 Assert.hasLength(schemaLanguage, "schemaLanguage is required");
144 for (Resource schema : schemas) {
145 Assert.isTrue(schema.exists(), "schema [" + schema + "] does not exist");
146 }
147 if (logger.isInfoEnabled()) {
148 logger.info("Validating using " + StringUtils.arrayToCommaDelimitedString(schemas));
149 }
150 validator = XmlValidatorFactory.createValidator(schemas, schemaLanguage);
151 }
152 Assert.notNull(validator, "Setting 'schema', 'schemas', 'xsdSchema', or 'xsdSchemaCollection' is required");
153 }
154
155
156
157
158
159
160
161
162
163
164
165 public boolean handleRequest(MessageContext messageContext) throws WebServiceClientException {
166 if (validateRequest) {
167 Source requestSource = getValidationRequestSource(messageContext.getRequest());
168 if (requestSource != null) {
169 SAXParseException[] errors;
170 try {
171 errors = validator.validate(requestSource);
172 }
173 catch (IOException e) {
174 throw new WebServiceIOException("Could not validate response: " + e.getMessage(), e);
175 }
176 if (!ObjectUtils.isEmpty(errors)) {
177 return handleRequestValidationErrors(messageContext, errors);
178 }
179 else if (logger.isDebugEnabled()) {
180 logger.debug("Request message validated");
181 }
182 }
183 }
184 return true;
185 }
186
187
188
189
190
191
192
193
194
195
196
197 protected boolean handleRequestValidationErrors(MessageContext messageContext, SAXParseException[] errors) {
198 for (SAXParseException error : errors) {
199 logger.error("XML validation error on request: " + error.getMessage());
200 }
201 throw new WebServiceValidationException(errors);
202 }
203
204
205
206
207
208
209
210
211
212
213
214
215 public boolean handleResponse(MessageContext messageContext) throws WebServiceClientException {
216 if (validateResponse) {
217 Source responseSource = getValidationResponseSource(messageContext.getResponse());
218 if (responseSource != null) {
219 SAXParseException[] errors;
220 try {
221 errors = validator.validate(responseSource);
222 }
223 catch (IOException e) {
224 throw new WebServiceIOException("Could not validate response: " + e.getMessage(), e);
225 }
226 if (!ObjectUtils.isEmpty(errors)) {
227 return handleResponseValidationErrors(messageContext, errors);
228 }
229 else if (logger.isDebugEnabled()) {
230 logger.debug("Response message validated");
231 }
232 }
233 }
234 return true;
235 }
236
237
238
239
240
241
242
243
244
245
246
247 protected boolean handleResponseValidationErrors(MessageContext messageContext, SAXParseException[] errors)
248 throws WebServiceValidationException {
249 for (SAXParseException error : errors) {
250 logger.warn("XML validation error on response: " + error.getMessage());
251 }
252 return false;
253 }
254
255
256 public boolean handleFault(MessageContext messageContext) throws WebServiceClientException {
257 return true;
258 }
259
260
261
262
263
264
265
266 protected abstract Source getValidationRequestSource(WebServiceMessage request);
267
268
269
270
271
272
273
274 protected abstract Source getValidationResponseSource(WebServiceMessage response);
275 }