From: <bo...@us...> - 2009-05-28 13:07:19
|
Revision: 339 http://xmlunit.svn.sourceforge.net/xmlunit/?rev=339&view=rev Author: bodewig Date: 2009-05-28 13:07:01 +0000 (Thu, 28 May 2009) Log Message: ----------- JAXP implementation of Validator Modified Paths: -------------- trunk/xmlunit/src/main/java-core/net/sf/xmlunit/validation/ValidationProblem.java trunk/xmlunit/src/main/java-core/net/sf/xmlunit/validation/Validator.java trunk/xmlunit/src/main/java-legacy/org/custommonkey/xmlunit/jaxp13/Validator.java Added Paths: ----------- trunk/xmlunit/src/main/java-core/net/sf/xmlunit/validation/JAXPValidator.java trunk/xmlunit/src/tests/java-core/net/sf/xmlunit/validation/ trunk/xmlunit/src/tests/java-core/net/sf/xmlunit/validation/JAXPValidatorTest.java Added: trunk/xmlunit/src/main/java-core/net/sf/xmlunit/validation/JAXPValidator.java =================================================================== --- trunk/xmlunit/src/main/java-core/net/sf/xmlunit/validation/JAXPValidator.java (rev 0) +++ trunk/xmlunit/src/main/java-core/net/sf/xmlunit/validation/JAXPValidator.java 2009-05-28 13:07:01 UTC (rev 339) @@ -0,0 +1,127 @@ +/* + This file is licensed to You 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 net.sf.xmlunit.validation; + +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import javax.xml.transform.Source; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; +import net.sf.xmlunit.exceptions.XMLUnitException; +import org.xml.sax.ErrorHandler; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; + +/** + * Validator using the javax.xml.validation namespace. + */ +public class JAXPValidator extends Validator { + private final String language; + private final SchemaFactory factory; + + public JAXPValidator(String language) { + this(language, null); + } + + public JAXPValidator(String language, SchemaFactory factory) { + this.language = language; + this.factory = factory; + } + + private SchemaFactory getFactory() { + return factory == null ? SchemaFactory.newInstance(language) : factory; + } + + @Override public ValidationResult validateSchema() { + ValidationHandler v = new ValidationHandler(); + SchemaFactory f = getFactory(); + f.setErrorHandler(v); + try { + f.newSchema(getSchemaSources()); + } catch (SAXException e) { + if (e instanceof SAXParseException) { + v.error((SAXParseException) e); + } else { + throw new XMLUnitException(e); + } + } finally { + f.setErrorHandler(null); + } + return v.getResult(); + } + + @Override public ValidationResult validateInstance(Source s) { + Schema schema; + try { + schema = getFactory().newSchema(getSchemaSources()); + } catch (SAXException e) { + throw new XMLUnitException("The schema is invalid", e); + } + ValidationHandler v = new ValidationHandler(); + javax.xml.validation.Validator val = schema.newValidator(); + val.setErrorHandler(v); + try { + val.validate(s); + } catch (SAXException e) { + if (e instanceof SAXParseException) { + v.error((SAXParseException) e); + } else { + throw new XMLUnitException(e); + } + } catch (java.io.IOException e) { + throw new XMLUnitException(e); + } + return v.getResult(); + } + + + private static class ValidationHandler implements ErrorHandler { + private List<ValidationProblem> problems = + new LinkedList<ValidationProblem>(); + private boolean valid = true; + // fatal errors are re-thrown by the parser + private SAXParseException lastFatalError = null; + + public void error(SAXParseException e) { + if (e != lastFatalError) { + valid = false; + problems.add(ValidationProblem.fromException(e, + ValidationProblem + .ProblemType.ERROR) + ); + } + } + + public void fatalError(SAXParseException e) { + valid = false; + lastFatalError = e; + problems.add(ValidationProblem.fromException(e, + ValidationProblem + .ProblemType.ERROR)); + } + + public void warning(SAXParseException e) { + problems.add(ValidationProblem.fromException(e, + ValidationProblem + .ProblemType.WARNING)); + } + + private ValidationResult getResult() { + return new ValidationResult(valid, + Collections.unmodifiableList(problems) + ); + } + } +} Property changes on: trunk/xmlunit/src/main/java-core/net/sf/xmlunit/validation/JAXPValidator.java ___________________________________________________________________ Added: svn:eol-style + native Modified: trunk/xmlunit/src/main/java-core/net/sf/xmlunit/validation/ValidationProblem.java =================================================================== --- trunk/xmlunit/src/main/java-core/net/sf/xmlunit/validation/ValidationProblem.java 2009-05-27 14:47:22 UTC (rev 338) +++ trunk/xmlunit/src/main/java-core/net/sf/xmlunit/validation/ValidationProblem.java 2009-05-28 13:07:01 UTC (rev 339) @@ -13,6 +13,8 @@ */ package net.sf.xmlunit.validation; +import org.xml.sax.SAXParseException; + /** * A validation "problem" which may be an error or a warning. */ @@ -60,4 +62,15 @@ public String getMessage() { return message; } + + static ValidationProblem fromException(SAXParseException e, + ProblemType type) { + return new ValidationProblem(e.getMessage(), + e.getLineNumber() > 0 + ? e.getLineNumber() : UNKNOWN, + e.getColumnNumber() > 0 + ? e.getColumnNumber() : UNKNOWN, + type); + } + } Modified: trunk/xmlunit/src/main/java-core/net/sf/xmlunit/validation/Validator.java =================================================================== --- trunk/xmlunit/src/main/java-core/net/sf/xmlunit/validation/Validator.java 2009-05-27 14:47:22 UTC (rev 338) +++ trunk/xmlunit/src/main/java-core/net/sf/xmlunit/validation/Validator.java 2009-05-28 13:07:01 UTC (rev 339) @@ -55,7 +55,7 @@ } protected Source[] getSchemaSources() { - return sourceLocations; + return sourceLocations == null ? new Source[0] : sourceLocations; } /** Modified: trunk/xmlunit/src/main/java-legacy/org/custommonkey/xmlunit/jaxp13/Validator.java =================================================================== --- trunk/xmlunit/src/main/java-legacy/org/custommonkey/xmlunit/jaxp13/Validator.java 2009-05-27 14:47:22 UTC (rev 338) +++ trunk/xmlunit/src/main/java-legacy/org/custommonkey/xmlunit/jaxp13/Validator.java 2009-05-28 13:07:01 UTC (rev 339) @@ -38,13 +38,13 @@ import java.util.ArrayList; import java.util.List; -import javax.xml.XMLConstants; import javax.xml.transform.Source; -import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; +import net.sf.xmlunit.exceptions.XMLUnitException; +import net.sf.xmlunit.validation.JAXPValidator; +import net.sf.xmlunit.validation.Languages; +import net.sf.xmlunit.validation.ValidationProblem; import org.custommonkey.xmlunit.exceptions.XMLUnitRuntimeException; -import org.xml.sax.ErrorHandler; -import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; /** @@ -56,15 +56,14 @@ * by your SchemaFactory implementation.</p> */ public class Validator { - private final String schemaLanguage; - private final SchemaFactory factory; - private final ArrayList sources = new ArrayList(); + private final ArrayList<Source> sources = new ArrayList<Source>(); + private final JAXPValidator validator; /** * validates using W3C XML Schema 1.0. */ public Validator() { - this(XMLConstants.W3C_XML_SCHEMA_NS_URI, null); + this(Languages.W3C_XML_SCHEMA_NS_URI, null); } /** @@ -93,8 +92,7 @@ * non-null, the first argument will be ignored. */ protected Validator(String schemaLanguage, SchemaFactory factory) { - this.schemaLanguage = schemaLanguage; - this.factory = factory; + validator = new JAXPValidator(schemaLanguage, factory); } /** @@ -102,13 +100,14 @@ */ public void addSchemaSource(Source s) { sources.add(s); + validator.setSchemaSources(sources.toArray(new Source[0])); } /** * Is the given schema definition valid? */ public boolean isSchemaValid() { - return getSchemaErrors().size() == 0; + return validator.validateSchema().isValid(); } /** @@ -117,27 +116,8 @@ * <p>The list contains {@link org.xml.sax.SAXParseException * SAXParseException}s.</p> */ - public List/*<SAXParseException>*/ getSchemaErrors() { - final ArrayList l = new ArrayList(); - try { - parseSchema(new CollectingErrorHandler(l)); - } catch (SAXException e) { - // error should have been recorded in our ErrorHandler, at - // least that's what the Javadocs say "SchemaFactory is - // not allowed to throw SAXException without first - // reporting it to ErrorHandler.". - // - // Unfortunately not all implementations seem to follow - // this rule. In particular using the setup described in - // org.custommonkey.xmlunit.jaxp13.test_Validator#XtestGoodRelaxNGCompactSyntaxIsValid() - // an exception ("SAXParseException: Content is not - // allowed in prolog.") will be thrown that never enters - // our Errorhandler. - if (l.size() == 0) { - l.add(e); - } - } - return l; + public List<SAXParseException> getSchemaErrors() { + return problemToExceptionList(validator.validateSchema().getProblems()); } /** @@ -150,9 +130,12 @@ * javax.xml.validation.Validator#validate validate in * Validator}). */ - public boolean isInstanceValid(Source instance) - throws XMLUnitRuntimeException { - return getInstanceErrors(instance).size() == 0; + public boolean isInstanceValid(Source instance) { + try { + return validator.validateInstance(instance).isValid(); + } catch (XMLUnitException e) { + throw new XMLUnitRuntimeException(e.getMessage(), e.getCause()); + } } /** @@ -167,59 +150,23 @@ * javax.xml.validation.Validator#validate validate in * Validator}). */ - public List/*<SAXParseException>*/ getInstanceErrors(Source instance) - throws XMLUnitRuntimeException { - Schema schema = null; + public List<SAXParseException> getInstanceErrors(Source instance) { try { - schema = parseSchema(null); - } catch (SAXException e) { - throw new XMLUnitRuntimeException("Schema is invalid", e); + return problemToExceptionList(validator.validateInstance(instance). + getProblems()); + } catch (XMLUnitException e) { + throw new XMLUnitRuntimeException(e.getMessage(), e.getCause()); } + } - final ArrayList l = new ArrayList(); - javax.xml.validation.Validator v = schema.newValidator(); - v.setErrorHandler(new CollectingErrorHandler(l)); - try { - v.validate(instance); - } catch (SAXException e) { - // error should have been recorded in our ErrorHandler, - // but better double-check. - if (l.size() == 0) { - l.add(e); - } - } catch (java.io.IOException i) { - throw new XMLUnitRuntimeException("Error reading instance source", - i); + private static List<SAXParseException> + problemToExceptionList(Iterable<ValidationProblem> problems) { + final List<SAXParseException> l = new ArrayList<SAXParseException>(); + for (ValidationProblem p : problems) { + l.add(new SAXParseException(p.getMessage(), + null, null, + p.getLine(), p.getColumn())); } return l; } - - private Schema parseSchema(ErrorHandler h) throws SAXException { - SchemaFactory fac = factory != null ? factory - : SchemaFactory.newInstance(schemaLanguage); - fac.setErrorHandler(h); - try { - return fac.newSchema((Source[]) - sources.toArray(new Source[sources.size()])); - } finally { - fac.setErrorHandler(null); - } - } - - private static final class CollectingErrorHandler implements ErrorHandler { - private final List l; - - CollectingErrorHandler(List l) { - this.l = l; - } - public void error(SAXParseException e) { - l.add(e); - } - public void fatalError(SAXParseException e) { - l.add(e); - } - public void warning(SAXParseException e) { - l.add(e); - } - } } Added: trunk/xmlunit/src/tests/java-core/net/sf/xmlunit/validation/JAXPValidatorTest.java =================================================================== --- trunk/xmlunit/src/tests/java-core/net/sf/xmlunit/validation/JAXPValidatorTest.java (rev 0) +++ trunk/xmlunit/src/tests/java-core/net/sf/xmlunit/validation/JAXPValidatorTest.java 2009-05-28 13:07:01 UTC (rev 339) @@ -0,0 +1,78 @@ +/* + This file is licensed to You 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 net.sf.xmlunit.validation; + +import java.io.File; +import javax.xml.transform.stream.StreamSource; +import net.sf.xmlunit.exceptions.XMLUnitException; +import static org.hamcrest.core.Is.*; +import static org.junit.Assert.*; +import org.junit.Test; + +public class JAXPValidatorTest { + + @Test public void shouldSuccessfullyValidateSchema() { + JAXPValidator v = new JAXPValidator(Languages.W3C_XML_SCHEMA_NS_URI); + v.setSchemaSource(new StreamSource(new File("src/tests/resources/Book.xsd"))); + ValidationResult r = v.validateSchema(); + assertTrue(r.isValid()); + assertFalse(r.getProblems().iterator().hasNext()); + } + + @Test public void shouldSuccessfullyValidateInstance() { + JAXPValidator v = new JAXPValidator(Languages.W3C_XML_SCHEMA_NS_URI); + v.setSchemaSource(new StreamSource(new File("src/tests/resources/Book.xsd"))); + ValidationResult r = v.validateInstance(new StreamSource(new File("src/tests/resources/BookXsdGenerated.xml"))); + assertTrue(r.isValid()); + assertFalse(r.getProblems().iterator().hasNext()); + } + + @Test public void shouldFailOnBrokenSchema() { + JAXPValidator v = new JAXPValidator(Languages.W3C_XML_SCHEMA_NS_URI); + v.setSchemaSource(new StreamSource(new File("src/tests/resources/broken.xsd"))); + ValidationResult r = v.validateSchema(); + assertFalse(r.isValid()); + assertTrue(r.getProblems().iterator().hasNext()); + } + + @Test public void shouldFailOnBrokenInstance() { + JAXPValidator v = new JAXPValidator(Languages.W3C_XML_SCHEMA_NS_URI); + v.setSchemaSource(new StreamSource(new File("src/tests/resources/Book.xsd"))); + ValidationResult r = v.validateInstance(new StreamSource(new File("src/tests/resources/invalidBook.xml"))); + assertFalse(r.isValid()); + assertTrue(r.getProblems().iterator().hasNext()); + } + + @Test public void shouldThrowWhenValidatingInstanceAndSchemaIsInvalid() { + JAXPValidator v = new JAXPValidator(Languages.W3C_XML_SCHEMA_NS_URI); + v.setSchemaSource(new StreamSource(new File("src/tests/resources/broken.xsd"))); + try { + v.validateInstance(new StreamSource(new File("src/tests/resources/BookXsdGenerated.xml"))); + fail("should have thrown an exception"); + } catch (Exception e) { + assertThat(e, is(XMLUnitException.class)); + } + } + + @Test public void shouldThrowWhenValidatingInstanceAndSchemaIsNotThere() { + JAXPValidator v = new JAXPValidator(Languages.W3C_XML_SCHEMA_NS_URI); + v.setSchemaSource(new StreamSource(new File("src/tests/resources/foo.xsd"))); + try { + v.validateInstance(new StreamSource(new File("src/tests/resources/BookXsdGenerated.xml"))); + fail("should have thrown an exception"); + } catch (Exception e) { + assertThat(e, is(XMLUnitException.class)); + } + } +} Property changes on: trunk/xmlunit/src/tests/java-core/net/sf/xmlunit/validation/JAXPValidatorTest.java ___________________________________________________________________ Added: svn:eol-style + native This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |