From 917f939ac7732ec30846e92ac3c6a0e145ee35f7 Mon Sep 17 00:00:00 2001 From: Arjen Poutsma Date: Wed, 5 Mar 2008 16:06:55 +0000 Subject: [PATCH] SWS-281 --- pom.xml | 1 + .../ws/wsdl/wsdl11/CommonXsdTest.java | 101 ------------------ .../springframework/xml/xsd/XsdSchema.java | 6 +- .../xml/xsd/commons/CommonsXsdSchema.java | 62 +---------- .../commons/CommonsXsdSchemaCollection.java | 92 +++++++++++++--- .../CommonsXsdSchemaCollectionTest.java | 70 ++++++++---- .../org/springframework/xml/xsd/ABC.xsd | 17 +++ .../org/springframework/xml/xsd/CD.xsd | 10 ++ 8 files changed, 154 insertions(+), 205 deletions(-) delete mode 100644 sandbox/src/test/java/org/springframework/ws/wsdl/wsdl11/CommonXsdTest.java create mode 100644 xml/src/test/resources/org/springframework/xml/xsd/ABC.xsd create mode 100644 xml/src/test/resources/org/springframework/xml/xsd/CD.xsd diff --git a/pom.xml b/pom.xml index 4da7223c..b3f996f0 100644 --- a/pom.xml +++ b/pom.xml @@ -662,6 +662,7 @@ http://jakarta.apache.org/commons/httpclient/apidocs/ http://ws.apache.org/wss4j/apidocs/ http://java.sun.com/javase/6/docs/jre/api/net/httpserver/spec/ + http://ws.apache.org/commons/XmlSchema/apidocs/ diff --git a/sandbox/src/test/java/org/springframework/ws/wsdl/wsdl11/CommonXsdTest.java b/sandbox/src/test/java/org/springframework/ws/wsdl/wsdl11/CommonXsdTest.java deleted file mode 100644 index ea2abc3c..00000000 --- a/sandbox/src/test/java/org/springframework/ws/wsdl/wsdl11/CommonXsdTest.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2008 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.ws.wsdl.wsdl11; - -import java.util.Iterator; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.stream.StreamResult; -import javax.xml.transform.dom.DOMSource; -import javax.xml.namespace.QName; - -import junit.framework.TestCase; -import org.apache.ws.commons.schema.XmlSchema; -import org.apache.ws.commons.schema.XmlSchemaCollection; -import org.apache.ws.commons.schema.XmlSchemaObjectTable; -import org.apache.ws.commons.schema.XmlSchemaObject; -import org.apache.ws.commons.schema.XmlSchemaSimpleType; -import org.apache.ws.commons.schema.XmlSchemaSimpleTypeRestriction; -import org.apache.ws.commons.schema.XmlSchemaComplexType; -import org.apache.ws.commons.schema.XmlSchemaSequence; -import org.apache.ws.commons.schema.XmlSchemaObjectCollection; -import org.apache.ws.commons.schema.XmlSchemaElement; -import org.apache.ws.commons.schema.XmlSchemaExternal; -import org.apache.ws.commons.schema.XmlSchemaInclude; -import org.apache.ws.commons.schema.XmlSchemaImport; -import org.w3c.dom.Document; - -import org.springframework.core.io.ClassPathResource; -import org.springframework.core.io.Resource; -import org.springframework.xml.sax.SaxUtils; - -/** - * @author Arjen Poutsma - * @since 1.5.0 - */ -public class CommonXsdTest extends TestCase { - - public void testIt() throws Exception { - XmlSchemaCollection collection = new XmlSchemaCollection(); - Resource r = new ClassPathResource("A.xsd", getClass()); - XmlSchema schema = collection.read(SaxUtils.createInputSource(r), null); - handleSchema(schema); - schema.write(System.out); - r = new ClassPathResource("D.xsd", getClass()); - schema = collection.read(SaxUtils.createInputSource(r), null); - handleSchema(schema); - schema.write(System.out); - } - - private void handleSchema(XmlSchema schema) { - if ("http://www.w3.org/2001/XMLSchema".equals(schema.getTargetNamespace())) { - return; - } - XmlSchemaObjectCollection includes = schema.getIncludes(); - for (int i = 0; i < includes.getCount(); i++) { - XmlSchemaExternal external = (XmlSchemaExternal) includes.getItem(i); - if (external instanceof XmlSchemaInclude) { - XmlSchema includedSchema = external.getSchema(); - handleSchema(includedSchema); - XmlSchemaObjectCollection includesItems = includedSchema.getItems(); - for (int j = 0; j < includesItems.getCount(); j++) { - schema.getItems().add(includesItems.getItem(j)); - } -// includes.remove(external); - schema.getItems().remove(external); - } - } - } - - private void dumpSchemaObject(XmlSchemaObject obj) { - System.out.println(obj); - if (obj instanceof XmlSchemaSimpleType) { - XmlSchemaSimpleType simpleType = (XmlSchemaSimpleType) obj; - XmlSchemaSimpleTypeRestriction restriction = (XmlSchemaSimpleTypeRestriction) simpleType.getContent(); - System.out.println("simple type with base name " + restriction.getBaseTypeName()); - } else if (obj instanceof XmlSchemaComplexType) { - XmlSchemaComplexType complexType = (XmlSchemaComplexType) obj; - XmlSchemaSequence seq = (XmlSchemaSequence) complexType.getParticle(); - System.out.println("complex type containing sequence"); - XmlSchemaObjectCollection seqCol = seq.getItems(); - for (int j = 0; j < seqCol.getCount(); j++) { - XmlSchemaElement element = (XmlSchemaElement) seqCol.getItem(j); - dumpSchemaObject(element.getSchemaType()); - } - } - } -} \ No newline at end of file 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 30a8d02a..27376c86 100644 --- a/xml/src/main/java/org/springframework/xml/xsd/XsdSchema.java +++ b/xml/src/main/java/org/springframework/xml/xsd/XsdSchema.java @@ -29,15 +29,15 @@ import javax.xml.transform.Source; public interface XsdSchema { /** - * Returns the target namespace of theis schema. + * Returns the target namespace of this schema. * * @return the target namespace */ String getTargetNamespace(); /** - * Returns the qualified names of all top-level elements declared in the schema. This excludes elements declared as child of - * another element, simplyType, or complexType. + * Returns the qualified names of all top-level elements declared in the schema. This excludes elements declared as + * child of another element, simplyType, or complexType. * * @return the top-level element names */ 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 8fb1e45e..c4a9c7d9 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,7 +18,6 @@ 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; @@ -27,9 +26,6 @@ import javax.xml.transform.Source; import javax.xml.transform.stream.StreamSource; import org.apache.ws.commons.schema.XmlSchema; -import org.apache.ws.commons.schema.XmlSchemaCollection; -import org.apache.ws.commons.schema.XmlSchemaObjectCollection; -import org.xml.sax.SAXException; import org.springframework.util.Assert; import org.springframework.xml.xsd.XsdSchema; @@ -43,7 +39,7 @@ import org.springframework.xml.xsd.XsdSchema; */ public class CommonsXsdSchema implements XsdSchema { - private XmlSchema schema; + private final XmlSchema schema; /** * Create a new instance of the {@link CommonsXsdSchema} class with the specified {@link XmlSchema} reference. @@ -70,17 +66,6 @@ public class CommonsXsdSchema implements XsdSchema { return (QName[]) result.toArray(new QName[result.size()]); } - public void merge(XsdSchema o) { - Assert.isInstanceOf(CommonsXsdSchema.class, o); - XmlSchema otherSchema = ((CommonsXsdSchema) o).schema; - Assert.isTrue(this.schema.getTargetNamespace().equals(otherSchema.getTargetNamespace()), - "Schema does not have same namespace"); - XmlSchemaObjectCollection otherItems = otherSchema.getItems(); - for (int i = 0; i < otherItems.getCount(); i++) { - schema.getItems().add(otherItems.getItem(i)); - } - } - public Source getSource() { ByteArrayOutputStream bos = new ByteArrayOutputStream(); schema.write(bos); @@ -93,51 +78,6 @@ public class CommonsXsdSchema implements XsdSchema { return schema; } - private void loadSchema() throws SAXException, IOException { - XmlSchemaCollection schemaCollection = new XmlSchemaCollection(); -// this.schema = schemaCollection.read(SaxUtils.createInputSource(xsdResource), null); - } - - /* - public XsdSchema[] inline() { - XmlSchema clone = cloneSchema(schema); - inlineIncludes(clone, new ArrayList()); - return new XsdSchema[]{new CommonsXsdSchema(clone)}; - } - - private static XmlSchema cloneSchema(XmlSchema schema) { - XmlSchemaCollection schemaCollection = new XmlSchemaCollection(); - XmlSchema clone = new XmlSchema(schemaCollection); - XmlSchemaObjectCollection originalItems = schema.getItems(); - XmlSchemaObjectCollection cloneItems = clone.getItems(); - for (int i = 0; i < originalItems.getCount(); i++) { - cloneItems.add(originalItems.getItem(i)); - } - return clone; - } - - private static void inlineIncludes(XmlSchema schema, List processedSchemas) { - processedSchemas.add(schema); - XmlSchemaObjectCollection includes = schema.getIncludes(); - for (int i = 0; i < includes.getCount(); i++) { - if (includes.getItem(i) instanceof XmlSchemaInclude) { - XmlSchemaInclude include = (XmlSchemaInclude) includes.getItem(i); - XmlSchema includedSchema = include.getSchema(); - XmlSchemaObjectCollection items = schema.getItems(); - if (!processedSchemas.contains(includedSchema)) { - inlineIncludes(includedSchema, processedSchemas); - XmlSchemaObjectCollection includesItems = includedSchema.getItems(); - for (int j = 0; j < includesItems.getCount(); j++) { - XmlSchemaObject includedItem = includesItems.getItem(j); - items.add(includedItem); - } - } - // remove the - items.remove(include); - } - } - }*/ - public String toString() { StringBuffer buffer = new StringBuffer("CommonsXsdSchema"); buffer.append('{'); 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 45ee2d30..07dbaea5 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 @@ -16,14 +16,18 @@ package org.springframework.xml.xsd.commons; +import java.io.IOException; import java.util.ArrayList; import java.util.List; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; +import org.apache.ws.commons.schema.ValidationEventHandler; import org.apache.ws.commons.schema.XmlSchema; import org.apache.ws.commons.schema.XmlSchemaCollection; -import org.apache.ws.commons.schema.constants.Constants; +import org.apache.ws.commons.schema.XmlSchemaExternal; +import org.apache.ws.commons.schema.XmlSchemaImport; +import org.apache.ws.commons.schema.XmlSchemaInclude; +import org.apache.ws.commons.schema.XmlSchemaObject; +import org.apache.ws.commons.schema.XmlSchemaObjectCollection; import org.springframework.beans.factory.InitializingBean; import org.springframework.core.io.Resource; @@ -34,6 +38,10 @@ import org.springframework.xml.xsd.XsdSchemaCollection; /** * Implementation of the {@link XsdSchemaCollection} that uses Apache WS-Commons XML Schema. + *

+ * Setting the {@link #setInline(boolean) inline} flag to true will result in all referenced schemas + * (included and imported) being merged into the referred schema. When including the schemas into a WSDL, this greatly + * simplifies the deloyment of the schemas. * * @author Arjen Poutsma * @see Commons XML Schema @@ -41,15 +49,15 @@ import org.springframework.xml.xsd.XsdSchemaCollection; */ public class CommonsXsdSchemaCollection implements XsdSchemaCollection, InitializingBean { - private static final Log logger = LogFactory.getLog(CommonsXsdSchemaCollection.class); - private final XmlSchemaCollection schemaCollection = new XmlSchemaCollection(); private final List xmlSchemas = new ArrayList(); private Resource[] xsdResources; - private boolean inlineIncludes = false; + private boolean inline = false; + + private ValidationEventHandler validationEventHandler; /** * Constructs a new, empty instance of the CommonsXsdSchemaCollection. @@ -82,15 +90,26 @@ public class CommonsXsdSchemaCollection implements XsdSchemaCollection, Initiali *

* Defaults to false. */ - public void setInlineIncludes(boolean inlineIncludes) { - this.inlineIncludes = inlineIncludes; + public void setInline(boolean inline) { + this.inline = inline; } - public void afterPropertiesSet() throws Exception { + /** Sets the WS-Commons validation event handler to use while parsing schemas. */ + public void setValidationEventHandler(ValidationEventHandler validationEventHandler) { + this.validationEventHandler = validationEventHandler; + } + + public void afterPropertiesSet() throws IOException { Assert.notEmpty(xsdResources, "'xsds' must not be empty"); for (int i = 0; i < xsdResources.length; i++) { Assert.isTrue(xsdResources[i].exists(), xsdResources[i] + " does not exit"); - xmlSchemas.add(schemaCollection.read(SaxUtils.createInputSource(xsdResources[i]), null)); + XmlSchema xmlSchema = + schemaCollection.read(SaxUtils.createInputSource(xsdResources[i]), validationEventHandler); + xmlSchemas.add(xmlSchema); + if (inline) { + inlineIncludes(xmlSchema, new ArrayList()); + findImports(xmlSchema, new ArrayList()); + } } } @@ -103,16 +122,55 @@ public class CommonsXsdSchemaCollection implements XsdSchemaCollection, Initiali return result; } + private void inlineIncludes(XmlSchema schema, List processedSchemas) { + processedSchemas.add(schema); + XmlSchemaObjectCollection includes = schema.getIncludes(); + for (int i = 0; i < includes.getCount(); i++) { + XmlSchemaExternal external = (XmlSchemaExternal) includes.getItem(i); + if (external instanceof XmlSchemaInclude) { + XmlSchema includedSchema = external.getSchema(); + XmlSchemaObjectCollection items = schema.getItems(); + if (!processedSchemas.contains(includedSchema)) { + inlineIncludes(includedSchema, processedSchemas); + findImports(includedSchema, new ArrayList()); + XmlSchemaObjectCollection includeItems = includedSchema.getItems(); + for (int j = 0; j < includeItems.getCount(); j++) { + XmlSchemaObject includedItem = includeItems.getItem(j); + items.add(includedItem); + } + } + // remove the + items.remove(external); + } + } + } + + private void findImports(XmlSchema schema, List processedSchemas) { + processedSchemas.add(schema); + XmlSchemaObjectCollection includes = schema.getIncludes(); + for (int i = 0; i < includes.getCount(); i++) { + XmlSchemaExternal external = (XmlSchemaExternal) includes.getItem(i); + if (external instanceof XmlSchemaImport) { + XmlSchema importedSchema = external.getSchema(); + if (!processedSchemas.contains(importedSchema)) { + inlineIncludes(importedSchema, processedSchemas); + findImports(importedSchema, processedSchemas); + xmlSchemas.add(importedSchema); + } + // remove the schemaLocation + external.setSchemaLocation(null); + } + } + } + public String toString() { StringBuffer buffer = new StringBuffer("CommonsXsdSchemaCollection"); buffer.append('{'); - XmlSchema[] schemas = schemaCollection.getXmlSchemas(); - for (int i = 0; i < schemas.length; i++) { - if (!Constants.URI_2001_SCHEMA_XSD.equals(schemas[i].getTargetNamespace())) { - buffer.append(schemas[i].getTargetNamespace()); - if (i < schemas.length - 1) { - buffer.append(','); - } + for (int i = 0; i < xmlSchemas.size(); i++) { + XmlSchema schema = (XmlSchema) xmlSchemas.get(i); + buffer.append(schema.getTargetNamespace()); + if (i < xmlSchemas.size() - 1) { + buffer.append(','); } } buffer.append('}'); 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 83c8ed0f..94f6219b 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 @@ -16,18 +16,38 @@ package org.springframework.xml.xsd.commons; -import junit.framework.TestCase; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMResult; + +import org.custommonkey.xmlunit.XMLTestCase; +import org.custommonkey.xmlunit.XMLUnit; +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.xsd.AbstractXsdSchemaTestCase; +import org.springframework.xml.xsd.XsdSchema; -public class CommonsXsdSchemaCollectionTest extends TestCase { +public class CommonsXsdSchemaCollectionTest extends XMLTestCase { private CommonsXsdSchemaCollection collection; + private Transformer transformer; + + private DocumentBuilder documentBuilder; + protected void setUp() throws Exception { collection = new CommonsXsdSchemaCollection(); + TransformerFactory transformerFactory = TransformerFactory.newInstance(); + transformer = transformerFactory.newTransformer(); + DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); + documentBuilderFactory.setNamespaceAware(true); + documentBuilder = documentBuilderFactory.newDocumentBuilder(); + XMLUnit.setIgnoreWhitespace(true); } public void testSingle() throws Exception { @@ -37,32 +57,36 @@ public class CommonsXsdSchemaCollectionTest extends TestCase { assertEquals("Invalid amount of XSDs loaded", 1, collection.getXsdSchemas().length); } - public void testIncludes() throws Exception { - Resource resource = new ClassPathResource("including.xsd", AbstractXsdSchemaTestCase.class); - collection.setXsds(new Resource[]{resource}); + public void testInlineComplex() throws Exception { + Resource a = new ClassPathResource("A.xsd", AbstractXsdSchemaTestCase.class); + collection.setXsds(new Resource[]{a}); + collection.setInline(true); collection.afterPropertiesSet(); - assertEquals("Invalid amount of XSDs loaded", 2, collection.getXsdSchemas().length); + XsdSchema[] schemas = collection.getXsdSchemas(); + assertEquals("Invalid amount of XSDs loaded", 2, schemas.length); + + assertEquals("Invalid target namespace", "urn:1", schemas[0].getTargetNamespace()); + Resource abc = new ClassPathResource("ABC.xsd", AbstractXsdSchemaTestCase.class); + Document expected = documentBuilder.parse(SaxUtils.createInputSource(abc)); + DOMResult domResult = new DOMResult(); + transformer.transform(schemas[0].getSource(), domResult); + assertXMLEqual("Invalid XSD generated", expected, (Document) domResult.getNode()); + + assertEquals("Invalid target namespace", "urn:2", schemas[1].getTargetNamespace()); + Resource cd = new ClassPathResource("CD.xsd", AbstractXsdSchemaTestCase.class); + expected = documentBuilder.parse(SaxUtils.createInputSource(cd)); + domResult = new DOMResult(); + transformer.transform(schemas[1].getSource(), domResult); + assertXMLEqual("Invalid XSD generated", expected, (Document) domResult.getNode()); } - public void testImports() throws Exception { - Resource resource = new ClassPathResource("importing.xsd", AbstractXsdSchemaTestCase.class); + public void testCircular() throws Exception { + Resource resource = new ClassPathResource("circular-1.xsd", AbstractXsdSchemaTestCase.class); collection.setXsds(new Resource[]{resource}); + collection.setInline(true); collection.afterPropertiesSet(); - assertEquals("Invalid amount of XSDs loaded", 2, collection.getXsdSchemas().length); - } - - public void testDuplicates() throws Exception { - Resource resource = new ClassPathResource("single.xsd", AbstractXsdSchemaTestCase.class); - collection.setXsds(new Resource[]{resource, resource}); - collection.afterPropertiesSet(); - assertEquals("Invalid amount of XSDs loaded", 1, collection.getXsdSchemas().length); - } - - public void testComplex() throws Exception { - Resource resource = new ClassPathResource("A.xsd", AbstractXsdSchemaTestCase.class); - collection.setXsds(new Resource[]{resource}); - collection.afterPropertiesSet(); - assertEquals("Invalid amount of XSDs loaded", 5, collection.getXsdSchemas().length); + XsdSchema[] schemas = collection.getXsdSchemas(); + assertEquals("Invalid amount of XSDs loaded", 1, schemas.length); } } \ 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 new file mode 100644 index 00000000..73c29e01 --- /dev/null +++ b/xml/src/test/resources/org/springframework/xml/xsd/ABC.xsd @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + diff --git a/xml/src/test/resources/org/springframework/xml/xsd/CD.xsd b/xml/src/test/resources/org/springframework/xml/xsd/CD.xsd new file mode 100644 index 00000000..0bb5b178 --- /dev/null +++ b/xml/src/test/resources/org/springframework/xml/xsd/CD.xsd @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file