diff --git a/core/src/main/java/org/springframework/ws/server/endpoint/interceptor/AbstractValidatingInterceptor.java b/core/src/main/java/org/springframework/ws/server/endpoint/interceptor/AbstractValidatingInterceptor.java index f91700dd..c23950df 100644 --- a/core/src/main/java/org/springframework/ws/server/endpoint/interceptor/AbstractValidatingInterceptor.java +++ b/core/src/main/java/org/springframework/ws/server/endpoint/interceptor/AbstractValidatingInterceptor.java @@ -20,6 +20,9 @@ import java.io.IOException; import javax.xml.transform.Source; import javax.xml.transform.TransformerException; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; + import org.springframework.beans.factory.InitializingBean; import org.springframework.core.io.Resource; import org.springframework.util.Assert; @@ -33,8 +36,8 @@ import org.springframework.ws.soap.SoapMessage; import org.springframework.xml.transform.TransformerObjectSupport; import org.springframework.xml.validation.XmlValidator; import org.springframework.xml.validation.XmlValidatorFactory; -import org.xml.sax.SAXException; -import org.xml.sax.SAXParseException; +import org.springframework.xml.xsd.XsdSchema; +import org.springframework.xml.xsd.XsdSchemaCollection; /** * Abstract base class for EndpointInterceptor implementations that validate part of the message using a @@ -81,6 +84,14 @@ public abstract class AbstractValidatingInterceptor extends TransformerObjectSup return schemas; } + /** + * Sets the schema resource to use for validation. Setting either this property or schemas is + * required. + */ + public void setSchema(Resource schema) { + setSchemas(new Resource[]{schema}); + } + /** * Sets the schema resources to use for validation. Setting either this property or schema is * required. @@ -95,11 +106,27 @@ public abstract class AbstractValidatingInterceptor extends TransformerObjectSup } /** - * Sets the schema resource to use for validation. Setting either this property or schemas is - * required. + * Sets the {@link XsdSchema} to use for validation. Setting this property, {@link + * #setXsdSchemaCollection(XsdSchemaCollection) xsdSchemaCollection}, {@link #setSchema(Resource) schema}, or {@link + * #setSchemas(Resource[]) schemas} is required. + * + * @param schema the xsd schema to use + * @throws IOException in case of I/O errors */ - public void setSchema(Resource schema) { - setSchemas(new Resource[]{schema}); + public void setXsdSchema(XsdSchema schema) throws IOException { + this.validator = schema.createValidator(); + } + + /** + * Sets the {@link XsdSchemaCollection} to use for validation. Setting this property, {@link + * #setXsdSchema(XsdSchema) xsdSchema}, {@link #setSchema(Resource) schema}, or {@link #setSchemas(Resource[]) + * schemas} is required. + * + * @param schemaCollection the xsd schema collection to use + * @throws IOException in case of I/O errors + */ + public void setXsdSchemaCollection(XsdSchemaCollection schemaCollection) throws IOException { + this.validator = schemaCollection.createValidator(); } /** Indicates whether the request should be validated against the schema. Default is true. */ @@ -113,15 +140,17 @@ public abstract class AbstractValidatingInterceptor extends TransformerObjectSup } public void afterPropertiesSet() throws Exception { - Assert.notEmpty(schemas, "setting either the schema or schemas property is required"); - Assert.hasLength(schemaLanguage, "schemaLanguage is required"); - for (int i = 0; i < schemas.length; i++) { - Assert.isTrue(schemas[i].exists(), "schema [" + schemas[i] + "] does not exist"); + if (validator == null && !ObjectUtils.isEmpty(schemas)) { + Assert.hasLength(schemaLanguage, "schemaLanguage is required"); + for (int i = 0; i < schemas.length; i++) { + Assert.isTrue(schemas[i].exists(), "schema [" + schemas[i] + "] does not exist"); + } + if (logger.isInfoEnabled()) { + logger.info("Validating using " + StringUtils.arrayToCommaDelimitedString(schemas)); + } + validator = XmlValidatorFactory.createValidator(schemas, schemaLanguage); } - if (logger.isInfoEnabled()) { - logger.info("Validating using " + StringUtils.arrayToCommaDelimitedString(schemas)); - } - validator = XmlValidatorFactory.createValidator(schemas, schemaLanguage); + Assert.notNull(validator, "Setting 'schema', 'schemas', 'xsdSchema', or 'xsdSchemaCollection' is required"); } /** diff --git a/core/src/main/java/org/springframework/ws/wsdl/wsdl11/provider/InliningXsdSchemaTypesProvider.java b/core/src/main/java/org/springframework/ws/wsdl/wsdl11/provider/InliningXsdSchemaTypesProvider.java index 52caaafe..be787445 100644 --- a/core/src/main/java/org/springframework/ws/wsdl/wsdl11/provider/InliningXsdSchemaTypesProvider.java +++ b/core/src/main/java/org/springframework/ws/wsdl/wsdl11/provider/InliningXsdSchemaTypesProvider.java @@ -16,6 +16,7 @@ package org.springframework.ws.wsdl.wsdl11.provider; +import java.io.IOException; import javax.wsdl.Definition; import javax.wsdl.Types; import javax.wsdl.WSDLException; @@ -32,6 +33,7 @@ import org.w3c.dom.Element; import org.springframework.util.Assert; import org.springframework.ws.wsdl.WsdlDefinitionException; import org.springframework.xml.transform.TransformerObjectSupport; +import org.springframework.xml.validation.XmlValidator; import org.springframework.xml.xsd.XsdSchema; import org.springframework.xml.xsd.XsdSchemaCollection; @@ -61,6 +63,10 @@ public class InliningXsdSchemaTypesProvider extends TransformerObjectSupport imp public XsdSchema[] getXsdSchemas() { return new XsdSchema[]{schema}; } + + public XmlValidator createValidator() throws IOException { + throw new UnsupportedOperationException(); + } }; } diff --git a/core/src/test/java/org/springframework/ws/soap/server/endpoint/interceptor/PayloadValidatingInterceptorTest.java b/core/src/test/java/org/springframework/ws/soap/server/endpoint/interceptor/PayloadValidatingInterceptorTest.java index 7983f80a..838d3b8f 100644 --- a/core/src/test/java/org/springframework/ws/soap/server/endpoint/interceptor/PayloadValidatingInterceptorTest.java +++ b/core/src/test/java/org/springframework/ws/soap/server/endpoint/interceptor/PayloadValidatingInterceptorTest.java @@ -28,6 +28,9 @@ import javax.xml.transform.TransformerFactory; import javax.xml.transform.stream.StreamSource; import org.custommonkey.xmlunit.XMLTestCase; +import org.xml.sax.SAXParseException; +import org.xml.sax.helpers.LocatorImpl; + import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.ws.MockWebServiceMessage; @@ -42,8 +45,7 @@ import org.springframework.ws.soap.saaj.SaajSoapMessageFactory; import org.springframework.ws.soap.saaj.support.SaajUtils; import org.springframework.ws.soap.soap11.Soap11Fault; import org.springframework.ws.soap.soap12.Soap12Fault; -import org.xml.sax.SAXParseException; -import org.xml.sax.helpers.LocatorImpl; +import org.springframework.xml.xsd.SimpleXsdSchema; public class PayloadValidatingInterceptorTest extends XMLTestCase { @@ -189,6 +191,7 @@ public class PayloadValidatingInterceptorTest extends XMLTestCase { System.setProperty("javax.xml.validation.SchemaFactory:" + XMLConstants.W3C_XML_SCHEMA_NS_URI, "org.apache.xerces.jaxp.validation.XMLSchemaFactory"); try { + PayloadValidatingInterceptor interceptor = new PayloadValidatingInterceptor(); interceptor.setSchema(new ClassPathResource(SCHEMA2, PayloadValidatingInterceptorTest.class)); interceptor.afterPropertiesSet(); MessageFactory messageFactory = MessageFactory.newInstance(); @@ -284,4 +287,21 @@ public class PayloadValidatingInterceptorTest extends XMLTestCase { } + public void testXsdSchema() throws Exception { + PayloadValidatingInterceptor interceptor = new PayloadValidatingInterceptor(); + SimpleXsdSchema schema = new SimpleXsdSchema(new ClassPathResource(SCHEMA, getClass())); + schema.afterPropertiesSet(); + interceptor.setXsdSchema(schema); + interceptor.setValidateRequest(true); + interceptor.setValidateResponse(true); + interceptor.afterPropertiesSet(); + MockWebServiceMessage request = new MockWebServiceMessage(); + request.setPayload(new ClassPathResource(VALID_MESSAGE, getClass())); + context = new DefaultMessageContext(request, new MockWebServiceMessageFactory()); + boolean result = interceptor.handleRequest(context, null); + assertTrue("Invalid response from interceptor", result); + assertFalse("Response set", context.hasResponse()); + + } + } \ No newline at end of file diff --git a/pom.xml b/pom.xml index da5a7ca8..b0e018af 100644 --- a/pom.xml +++ b/pom.xml @@ -1,5 +1,6 @@ - + 4.0.0 org.springframework.ws spring-ws @@ -491,6 +492,7 @@ maven-assembly-plugin + 2.2-beta-1 false @@ -515,6 +517,7 @@ maven-assembly-plugin + 2.2-beta-1 false @@ -590,19 +593,20 @@ - - + + - - - - + + + + - + diff --git a/xml/src/main/java/org/springframework/xml/xsd/SimpleXsdSchema.java b/xml/src/main/java/org/springframework/xml/xsd/SimpleXsdSchema.java index d8cc648c..dff46dab 100644 --- a/xml/src/main/java/org/springframework/xml/xsd/SimpleXsdSchema.java +++ b/xml/src/main/java/org/springframework/xml/xsd/SimpleXsdSchema.java @@ -17,8 +17,6 @@ package org.springframework.xml.xsd; import java.io.IOException; -import java.util.ArrayList; -import java.util.List; import javax.xml.namespace.QName; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; @@ -28,16 +26,15 @@ import javax.xml.transform.dom.DOMSource; import org.w3c.dom.Document; import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import org.springframework.beans.factory.InitializingBean; import org.springframework.core.io.Resource; import org.springframework.util.Assert; -import org.springframework.util.StringUtils; import org.springframework.xml.namespace.QNameUtils; import org.springframework.xml.sax.SaxUtils; +import org.springframework.xml.validation.XmlValidator; +import org.springframework.xml.validation.XmlValidatorFactory; /** * The default {@link XsdSchema} implementation. @@ -57,8 +54,6 @@ public class SimpleXsdSchema implements XsdSchema, InitializingBean { private static final QName SCHEMA_NAME = QNameUtils.createQName(SCHEMA_NAMESPACE, "schema", "xsd"); - private static final QName ELEMENT_NAME = QNameUtils.createQName(SCHEMA_NAMESPACE, "element", "xsd"); - private Resource xsdResource; private Element schemaElement; @@ -103,24 +98,8 @@ public class SimpleXsdSchema implements XsdSchema, InitializingBean { return new DOMSource(schemaElement); } - public QName[] getElementNames() { - NodeList children = schemaElement.getChildNodes(); - List result = new ArrayList(children.getLength()); - for (int i = 0; i < children.getLength(); i++) { - if (children.item(i).getNodeType() == Node.ELEMENT_NODE) { - Element childElement = (Element) children.item(i); - QName childName = QNameUtils.getQNameForNode(childElement); - if (ELEMENT_NAME.equals(childName)) { - result.add(getElementName(childElement)); - } - } - } - return (QName[]) result.toArray(new QName[result.size()]); - } - - private QName getElementName(Element element) { - String attributeValue = element.getAttribute("name"); - return StringUtils.hasLength(attributeValue) ? new QName(getTargetNamespace(), attributeValue) : null; + public XmlValidator createValidator() throws IOException { + return XmlValidatorFactory.createValidator(xsdResource, XmlValidatorFactory.SCHEMA_W3C_XML); } public void afterPropertiesSet() throws ParserConfigurationException, IOException, SAXException { diff --git a/xml/src/main/java/org/springframework/xml/xsd/XsdSchema.java b/xml/src/main/java/org/springframework/xml/xsd/XsdSchema.java index f6510837..bf01275b 100644 --- a/xml/src/main/java/org/springframework/xml/xsd/XsdSchema.java +++ b/xml/src/main/java/org/springframework/xml/xsd/XsdSchema.java @@ -16,8 +16,11 @@ package org.springframework.xml.xsd; +import java.io.IOException; import javax.xml.transform.Source; +import org.springframework.xml.validation.XmlValidator; + /** * Represents an abstraction for XSD schemas. * @@ -35,9 +38,17 @@ public interface XsdSchema { String getTargetNamespace(); /** - * Returns the Source of the schema. + * Returns the {@link Source} of the schema. * - * @return the Source of this XSD schema + * @return the source of this XSD schema */ Source getSource(); + + /** + * Creates a {@link XmlValidator} based on the schema. + * + * @return a validator for this schema + * @throws IOException in case of I/O errors + */ + XmlValidator createValidator() throws IOException; } diff --git a/xml/src/main/java/org/springframework/xml/xsd/XsdSchemaCollection.java b/xml/src/main/java/org/springframework/xml/xsd/XsdSchemaCollection.java index 3fefe614..e3cbfa1d 100644 --- a/xml/src/main/java/org/springframework/xml/xsd/XsdSchemaCollection.java +++ b/xml/src/main/java/org/springframework/xml/xsd/XsdSchemaCollection.java @@ -16,6 +16,10 @@ package org.springframework.xml.xsd; +import java.io.IOException; + +import org.springframework.xml.validation.XmlValidator; + /** * Represents an abstraction for a collection of XSD schemas. * @@ -25,9 +29,18 @@ package org.springframework.xml.xsd; public interface XsdSchemaCollection { /** - * Returns all schema's contained in this collection. + * Returns all schemas contained in this collection. * - * @return the schema's contained in this collection + * @return the schemas contained in this collection */ XsdSchema[] getXsdSchemas(); + + /** + * Creates a {@link XmlValidator} based on the schemas contained in this collection. + * + * @return a validator for this collection + * @throws IOException in case of I/O errors + */ + XmlValidator createValidator() throws IOException; + } diff --git a/xml/src/main/java/org/springframework/xml/xsd/commons/CommonsXsdSchema.java b/xml/src/main/java/org/springframework/xml/xsd/commons/CommonsXsdSchema.java index 368c6db0..ecf6ed4d 100644 --- a/xml/src/main/java/org/springframework/xml/xsd/commons/CommonsXsdSchema.java +++ b/xml/src/main/java/org/springframework/xml/xsd/commons/CommonsXsdSchema.java @@ -18,6 +18,7 @@ package org.springframework.xml.xsd.commons; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; +import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -32,7 +33,11 @@ import org.w3c.dom.Document; import org.springframework.beans.BeanInstantiationException; import org.springframework.beans.BeanUtils; +import org.springframework.core.io.Resource; +import org.springframework.core.io.UrlResource; import org.springframework.util.Assert; +import org.springframework.xml.validation.XmlValidator; +import org.springframework.xml.validation.XmlValidatorFactory; import org.springframework.xml.xsd.XsdSchema; /** @@ -91,6 +96,11 @@ public class CommonsXsdSchema implements XsdSchema { return new StreamSource(bis); } + public XmlValidator createValidator() throws IOException { + Resource resource = new UrlResource(schema.getSourceURI()); + return XmlValidatorFactory.createValidator(resource, XmlValidatorFactory.SCHEMA_W3C_XML); + } + /** Returns the wrapped Commons XmlSchema object. */ public XmlSchema getSchema() { return schema; diff --git a/xml/src/main/java/org/springframework/xml/xsd/commons/CommonsXsdSchemaCollection.java b/xml/src/main/java/org/springframework/xml/xsd/commons/CommonsXsdSchemaCollection.java index 07dbaea5..acc350fc 100644 --- a/xml/src/main/java/org/springframework/xml/xsd/commons/CommonsXsdSchemaCollection.java +++ b/xml/src/main/java/org/springframework/xml/xsd/commons/CommonsXsdSchemaCollection.java @@ -31,8 +31,11 @@ import org.apache.ws.commons.schema.XmlSchemaObjectCollection; import org.springframework.beans.factory.InitializingBean; import org.springframework.core.io.Resource; +import org.springframework.core.io.UrlResource; import org.springframework.util.Assert; import org.springframework.xml.sax.SaxUtils; +import org.springframework.xml.validation.XmlValidator; +import org.springframework.xml.validation.XmlValidatorFactory; import org.springframework.xml.xsd.XsdSchema; import org.springframework.xml.xsd.XsdSchemaCollection; @@ -122,6 +125,15 @@ public class CommonsXsdSchemaCollection implements XsdSchemaCollection, Initiali return result; } + public XmlValidator createValidator() throws IOException { + Resource[] resources = new Resource[xmlSchemas.size()]; + for (int i = xmlSchemas.size() - 1; i >= 0; i--) { + XmlSchema xmlSchema = (XmlSchema) xmlSchemas.get(i); + resources[i] = new UrlResource(xmlSchema.getSourceURI()); + } + return XmlValidatorFactory.createValidator(resources, XmlValidatorFactory.SCHEMA_W3C_XML); + } + private void inlineIncludes(XmlSchema schema, List processedSchemas) { processedSchemas.add(schema); XmlSchemaObjectCollection includes = schema.getIncludes(); diff --git a/xml/src/test/java/org/springframework/xml/xsd/commons/CommonsXsdSchemaCollectionTest.java b/xml/src/test/java/org/springframework/xml/xsd/commons/CommonsXsdSchemaCollectionTest.java index 94f6219b..43b18eb6 100644 --- a/xml/src/test/java/org/springframework/xml/xsd/commons/CommonsXsdSchemaCollectionTest.java +++ b/xml/src/test/java/org/springframework/xml/xsd/commons/CommonsXsdSchemaCollectionTest.java @@ -29,6 +29,7 @@ import org.w3c.dom.Document; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.xml.sax.SaxUtils; +import org.springframework.xml.validation.XmlValidator; import org.springframework.xml.xsd.AbstractXsdSchemaTestCase; import org.springframework.xml.xsd.XsdSchema; @@ -89,4 +90,13 @@ public class CommonsXsdSchemaCollectionTest extends XMLTestCase { assertEquals("Invalid amount of XSDs loaded", 1, schemas.length); } + public void testCreateValidator() throws Exception { + Resource a = new ClassPathResource("A.xsd", AbstractXsdSchemaTestCase.class); + collection.setXsds(new Resource[]{a}); + collection.setInline(true); + collection.afterPropertiesSet(); + + XmlValidator validator = collection.createValidator(); + assertNotNull("No XmlValidator returned", validator); + } } \ No newline at end of file diff --git a/xml/src/test/resources/org/springframework/xml/xsd/A.xsd b/xml/src/test/resources/org/springframework/xml/xsd/A.xsd index dd680b01..a2561e02 100644 --- a/xml/src/test/resources/org/springframework/xml/xsd/A.xsd +++ b/xml/src/test/resources/org/springframework/xml/xsd/A.xsd @@ -4,7 +4,9 @@ xmlns:tns="urn:1" elementFormDefault="qualified" attributeFormDefault="unqualified"> - - - + + + + + \ No newline at end of file diff --git a/xml/src/test/resources/org/springframework/xml/xsd/ABC.xsd b/xml/src/test/resources/org/springframework/xml/xsd/ABC.xsd index 73c29e01..0e7a89b3 100644 --- a/xml/src/test/resources/org/springframework/xml/xsd/ABC.xsd +++ b/xml/src/test/resources/org/springframework/xml/xsd/ABC.xsd @@ -2,9 +2,11 @@ - - - + + + + + diff --git a/xml/src/test/resources/org/springframework/xml/xsd/AbstractXsdSchemaTestCase.java b/xml/src/test/resources/org/springframework/xml/xsd/AbstractXsdSchemaTestCase.java index 3457bf67..2ae97150 100644 --- a/xml/src/test/resources/org/springframework/xml/xsd/AbstractXsdSchemaTestCase.java +++ b/xml/src/test/resources/org/springframework/xml/xsd/AbstractXsdSchemaTestCase.java @@ -29,6 +29,7 @@ import org.w3c.dom.Document; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.xml.sax.SaxUtils; +import org.springframework.xml.validation.XmlValidator; public abstract class AbstractXsdSchemaTestCase extends XMLTestCase { @@ -84,5 +85,12 @@ public abstract class AbstractXsdSchemaTestCase extends XMLTestCase { assertXMLEqual("Invalid Source returned", expected, result); } + public void testCreateValidator() throws Exception { + Resource resource = new ClassPathResource("single.xsd", AbstractXsdSchemaTestCase.class); + XsdSchema single = createSchema(resource); + XmlValidator validator = single.createValidator(); + assertNotNull("No XmlValidator returned", validator); + } + protected abstract XsdSchema createSchema(Resource resource) throws Exception; }