SWS-242 - Allow for custom ErrorHandler in PayloadValidatingInterceptor

This commit is contained in:
Arjen Poutsma
2011-03-24 10:12:51 +00:00
parent 04aab9f6b0
commit ba2744ab82
9 changed files with 161 additions and 38 deletions

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2005-2010 the original author or authors.
* Copyright 2005-2011 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
* 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,
@@ -31,6 +31,7 @@ import org.springframework.ws.server.EndpointInterceptor;
import org.springframework.ws.soap.SoapFault;
import org.springframework.ws.soap.SoapMessage;
import org.springframework.xml.transform.TransformerObjectSupport;
import org.springframework.xml.validation.ValidationErrorHandler;
import org.springframework.xml.validation.XmlValidator;
import org.springframework.xml.validation.XmlValidatorFactory;
import org.springframework.xml.xsd.XsdSchema;
@@ -65,6 +66,8 @@ public abstract class AbstractValidatingInterceptor extends TransformerObjectSup
private XmlValidator validator;
private ValidationErrorHandler errorHandler;
public String getSchemaLanguage() {
return schemaLanguage;
}
@@ -131,6 +134,15 @@ public abstract class AbstractValidatingInterceptor extends TransformerObjectSup
this.validator = schemaCollection.createValidator();
}
/**
* Sets the error handler to use for validation. If not set, a default error handler will be used.
*
* @param errorHandler the error handler.
*/
public void setErrorHandler(ValidationErrorHandler errorHandler) {
this.errorHandler = errorHandler;
}
/** Indicates whether the request should be validated against the schema. Default is <code>true</code>. */
public void setValidateRequest(boolean validateRequest) {
this.validateRequest = validateRequest;
@@ -171,7 +183,7 @@ public abstract class AbstractValidatingInterceptor extends TransformerObjectSup
if (validateRequest) {
Source requestSource = getValidationRequestSource(messageContext.getRequest());
if (requestSource != null) {
SAXParseException[] errors = validator.validate(requestSource);
SAXParseException[] errors = validator.validate(requestSource, errorHandler);
if (!ObjectUtils.isEmpty(errors)) {
return handleRequestValidationErrors(messageContext, errors);
}
@@ -213,7 +225,7 @@ public abstract class AbstractValidatingInterceptor extends TransformerObjectSup
if (validateResponse) {
Source responseSource = getValidationResponseSource(messageContext.getResponse());
if (responseSource != null) {
SAXParseException[] errors = validator.validate(responseSource);
SAXParseException[] errors = validator.validate(responseSource, errorHandler);
if (!ObjectUtils.isEmpty(errors)) {
return handleResponseValidationErrors(messageContext, errors);
}
@@ -227,11 +239,11 @@ public abstract class AbstractValidatingInterceptor extends TransformerObjectSup
/**
* Template method that is called when the response message contains validation errors. Default implementation logs
* all errors, and returns <code>false</code>, i.e. do not cot continue to process the respone interceptor chain.
* all errors, and returns <code>false</code>, i.e. do not cot continue to process the response interceptor chain.
*
* @param messageContext the message context
* @param errors the validation errors
* @return <code>true</code> to continue the reponse interceptor chain, <code>false</code> (the default) otherwise
* @return <code>true</code> to continue the response interceptor chain, <code>false</code> (the default) otherwise
*/
protected boolean handleResponseValidationErrors(MessageContext messageContext, SAXParseException[] errors) {
for (SAXParseException error : errors) {

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2005-2010 the original author or authors.
* Copyright 2005-2011 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
* 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,
@@ -44,11 +44,13 @@ import org.springframework.ws.soap.soap11.Soap11Fault;
import org.springframework.ws.soap.soap12.Soap12Fault;
import org.springframework.ws.transport.MockTransportInputStream;
import org.springframework.ws.transport.TransportInputStream;
import org.springframework.xml.validation.ValidationErrorHandler;
import org.springframework.xml.xsd.SimpleXsdSchema;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.LocatorImpl;
@@ -95,7 +97,7 @@ public class PayloadValidatingInterceptorTest {
@Test
public void testHandleInvalidRequestSoap11() throws Exception {
SoapMessage invalidMessage = (SoapMessage) soap11Factory.createWebServiceMessage();
SoapMessage invalidMessage = soap11Factory.createWebServiceMessage();
InputStream inputStream = getClass().getResourceAsStream(INVALID_MESSAGE);
transformer.transform(new StreamSource(inputStream), invalidMessage.getPayloadResult());
context = new DefaultMessageContext(invalidMessage, soap11Factory);
@@ -115,7 +117,7 @@ public class PayloadValidatingInterceptorTest {
@Test
public void testHandleInvalidRequestSoap12() throws Exception {
SoapMessage invalidMessage = (SoapMessage) soap12Factory.createWebServiceMessage();
SoapMessage invalidMessage = soap12Factory.createWebServiceMessage();
InputStream inputStream = getClass().getResourceAsStream(INVALID_MESSAGE);
transformer.transform(new StreamSource(inputStream), invalidMessage.getPayloadResult());
context = new DefaultMessageContext(invalidMessage, soap12Factory);
@@ -365,4 +367,31 @@ public class PayloadValidatingInterceptorTest {
}
@Test
public void customErrorHandler() throws Exception {
ValidationErrorHandler errorHandler = new ValidationErrorHandler() {
public SAXParseException[] getErrors() {
return new SAXParseException[0];
}
public void warning(SAXParseException exception) throws SAXException {
}
public void error(SAXParseException exception) throws SAXException {
}
public void fatalError(SAXParseException exception) throws SAXException {
}
};
interceptor.setErrorHandler(errorHandler);
SoapMessage invalidMessage = soap11Factory.createWebServiceMessage();
InputStream inputStream = getClass().getResourceAsStream(INVALID_MESSAGE);
transformer.transform(new StreamSource(inputStream), invalidMessage.getPayloadResult());
context = new DefaultMessageContext(invalidMessage, soap11Factory);
boolean result = interceptor.handleRequest(context, null);
Assert.assertTrue("Invalid response from interceptor", result);
Assert.assertFalse("Context has response", context.hasResponse());
}
}

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2005-2010 the original author or authors.
* Copyright 2005-2011 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
* 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,
@@ -46,7 +46,9 @@ import org.xml.sax.helpers.DefaultHandler;
*
* @author Arjen Poutsma
* @since 1.0.0
* @deprecated in favor of {@link Jaxp13ValidatorFactory}
*/
@Deprecated
abstract class Jaxp10ValidatorFactory {
private static final String SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
@@ -80,9 +82,14 @@ abstract class Jaxp10ValidatorFactory {
parserFactory.setValidating(true);
}
public SAXParseException[] validate(Source source, ValidationErrorHandler errorHandler)
throws IOException {
return validate(source);
}
public SAXParseException[] validate(Source source) throws IOException {
SAXParser parser = createSAXParser();
ValidationErrorHandler errorHandler = new ValidationErrorHandler();
DefaultValidationErrorHandler errorHandler = new DefaultValidationErrorHandler();
try {
if (source instanceof SAXSource) {
validateSAXSource((SAXSource) source, parser, errorHandler);
@@ -104,7 +111,7 @@ abstract class Jaxp10ValidatorFactory {
}
}
private void validateDOMSource(DOMSource domSource, SAXParser parser, ValidationErrorHandler errorHandler)
private void validateDOMSource(DOMSource domSource, SAXParser parser, DefaultValidationErrorHandler errorHandler)
throws IOException, SAXException {
try {
// Sadly, JAXP 1.0 DOM doesn't implement DOM level 3, so we cannot use Document.normalizeDocument()
@@ -123,7 +130,7 @@ abstract class Jaxp10ValidatorFactory {
private void validateStreamSource(StreamSource streamSource,
SAXParser parser,
ValidationErrorHandler errorHandler) throws SAXException, IOException {
DefaultValidationErrorHandler errorHandler) throws SAXException, IOException {
if (streamSource.getInputStream() != null) {
parser.parse(streamSource.getInputStream(), errorHandler);
}
@@ -135,7 +142,7 @@ abstract class Jaxp10ValidatorFactory {
}
}
private void validateSAXSource(SAXSource source, SAXParser parser, ValidationErrorHandler errorHandler)
private void validateSAXSource(SAXSource source, SAXParser parser, DefaultValidationErrorHandler errorHandler)
throws SAXException, IOException {
parser.parse(source.getInputSource(), errorHandler);
}
@@ -157,7 +164,7 @@ abstract class Jaxp10ValidatorFactory {
}
/** <code>DefaultHandler</code> extension that stores errors and fatal errors in a list. */
private static class ValidationErrorHandler extends DefaultHandler {
private static class DefaultValidationErrorHandler extends DefaultHandler {
private List<SAXParseException> errors = new ArrayList<SAXParseException>();

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2005-2010 the original author or authors.
* Copyright 2005-2011 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
* 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,
@@ -21,10 +21,10 @@ import java.util.ArrayList;
import java.util.List;
import javax.xml.transform.Source;
import javax.xml.validation.Schema;
import javax.xml.validation.Validator;
import org.springframework.core.io.Resource;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
@@ -55,8 +55,14 @@ abstract class Jaxp13ValidatorFactory {
}
public SAXParseException[] validate(Source source) throws IOException {
javax.xml.validation.Validator validator = schema.newValidator();
ValidationErrorHandler errorHandler = new ValidationErrorHandler();
return validate(source, null);
}
public SAXParseException[] validate(Source source, ValidationErrorHandler errorHandler) throws IOException {
if (errorHandler == null) {
errorHandler = new DefaultValidationErrorHandler();
}
Validator validator = schema.newValidator();
validator.setErrorHandler(errorHandler);
try {
validator.validate(source);
@@ -69,11 +75,11 @@ abstract class Jaxp13ValidatorFactory {
}
/** <code>ErrorHandler</code> implementation that stores errors and fatal errors in a list. */
private static class ValidationErrorHandler implements ErrorHandler {
private static class DefaultValidationErrorHandler implements ValidationErrorHandler {
private List<SAXParseException> errors = new ArrayList<SAXParseException>();
private SAXParseException[] getErrors() {
public SAXParseException[] getErrors() {
return errors.toArray(new SAXParseException[errors.size()]);
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2005-2011 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.xml.validation;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXParseException;
/**
* Subinterface of {@link ErrorHandler} that allows the registered errors to be retrieved.
* @author Arjen Poutsma
* @since 2.0.1
*/
public interface ValidationErrorHandler extends ErrorHandler {
/**
* Returns the errors collected by this error handler.
* @return the errors
*/
SAXParseException[] getErrors();
}

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2006 the original author or authors.
* Copyright 2005-2011 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
* 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,
@@ -27,7 +27,7 @@ import org.xml.sax.SAXParseException;
* Instances of this class are designed to be thread safe.
*
* @author Arjen Poutsma
* @see XmlValidatorFactory#createValidator(org.springframework.core.io.Resource,String)
* @see XmlValidatorFactory#createValidator(org.springframework.core.io.Resource, String)
* @since 1.0.0
*/
public interface XmlValidator {
@@ -43,4 +43,16 @@ public interface XmlValidator {
*/
SAXParseException[] validate(Source source) throws IOException;
/**
* Validates the given {@link Source} and {@link ValidationErrorHandler}, and returns an array of {@link
* SAXParseException}s as result. The array will be empty if no validation errors are found.
*
* @param source the input document
* @param errorHandler the error handler to use. May be {@code null}, in which case a default will be used.
* @return an array of <code>SAXParseException</code>s
* @throws IOException if the <code>source</code> cannot be read
* @throws XmlValidationException if the <code>source</code> cannot be validated
*/
SAXParseException[] validate(Source source, ValidationErrorHandler errorHandler) throws IOException;
}

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2005-2010 the original author or authors.
* Copyright 2005-2011 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
* 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,
@@ -91,12 +91,8 @@ public abstract class XmlValidatorFactory {
logger.trace("Creating JAXP 1.3 XmlValidator");
return Jaxp13ValidatorFactory.createValidator(schemaResources, schemaLanguage);
}
else if (JaxpVersion.getJaxpVersion() >= JaxpVersion.JAXP_10) {
logger.trace("Creating JAXP 1.0 XmlValidator");
return Jaxp10ValidatorFactory.createValidator(schemaResources, schemaLanguage);
}
else {
throw new IllegalStateException("Could not locate JAXP 1.0 or higher.");
throw new IllegalStateException("Could not locate JAXP 1.3.");
}
}

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2005-2010 the original author or authors.
* Copyright 2005-2011 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
* 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,
@@ -33,6 +33,7 @@ import org.junit.Before;
import org.junit.Test;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
public abstract class AbstractValidatorFactoryTestCase {
@@ -135,4 +136,25 @@ public abstract class AbstractValidatorFactoryTestCase {
Assert.assertEquals("ValidationErrors returned", 0, errors.length);
}
@Test
public void customErrorHandler() throws Exception {
ValidationErrorHandler myHandler = new ValidationErrorHandler() {
public SAXParseException[] getErrors() {
return new SAXParseException[0];
}
public void warning(SAXParseException exception) throws SAXException {
}
public void error(SAXParseException exception) throws SAXException {
}
public void fatalError(SAXParseException exception) throws SAXException {
}
};
SAXParseException[] errors = validator.validate(new StreamSource(invalidInputStream), myHandler);
Assert.assertNotNull("Null returned for errors", errors);
Assert.assertEquals("ValidationErrors returned", 0, errors.length);
}
}

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2005-2010 the original author or authors.
* Copyright 2005-2011 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
* 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,
@@ -26,4 +26,9 @@ public class Jaxp10ValidatorFactoryTest extends AbstractValidatorFactoryTestCase
protected XmlValidator createValidator(Resource[] schemaResources, String schemaLanguage) throws IOException {
return Jaxp10ValidatorFactory.createValidator(schemaResources, schemaLanguage);
}
@Override
public void customErrorHandler() throws Exception {
// Not supported on JAXP 1.0
}
}