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