package org.tigris.juxy.validator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.tigris.juxy.JuxyRuntimeException; import org.tigris.juxy.util.ArgumentAssert; import org.tigris.juxy.util.ExceptionUtil; import org.tigris.juxy.util.JuxyURIResolver; import org.w3c.dom.Node; import org.xml.sax.ErrorHandler; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; import javax.xml.XMLConstants; import javax.xml.transform.Source; import javax.xml.transform.dom.DOMSource; import javax.xml.validation.SchemaFactory; import java.io.IOException; /** * @author pavel */ public class XMLSchemaValidator implements Validator { private static SchemaFactory schemaFactory = null; private javax.xml.validation.Validator validator; private SchemaErrorHandler errorHandler; public XMLSchemaValidator(String pathToSchema) { ArgumentAssert.notEmpty(pathToSchema, "Path must not be empty"); if (schemaFactory == null) { schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); } SchemaErrorHandler schemaErrorHandler = new SchemaErrorHandler(); schemaFactory.setErrorHandler(schemaErrorHandler); try { JuxyURIResolver resolver = new JuxyURIResolver(); Source schemaSrc = resolver.resolve(pathToSchema, ""); if (schemaSrc == null) { throw new ValidationFailedException("Unable to locate schema by specified path: " + pathToSchema); } validator = schemaFactory.newSchema(schemaSrc).newValidator(); if (schemaErrorHandler.wereErrors()) { throw new ValidationFailedException(exceptionMessage("Failed to compile schema", schemaErrorHandler)); } errorHandler = new SchemaErrorHandler(); validator.setErrorHandler(errorHandler); } catch (SAXException e) { throw new ValidationFailedException(exceptionMessage("Failed to compile schema", schemaErrorHandler)); } } public void validate(Node node) throws ValidationFailedException { ArgumentAssert.notNull(node, "Node must not be null"); errorHandler.reset(); Source src = new DOMSource(node); try { validator.validate(src); if (errorHandler.wereErrors()) { throw new ValidationFailedException(exceptionMessage("Validation failed", errorHandler)); } } catch (SAXException e) { throw new ValidationFailedException(exceptionMessage("Validation failed", errorHandler)); } catch (IOException e) { throw new ValidationFailedException(exceptionMessage("Validation failed", errorHandler)); } } private String exceptionMessage(String prefix, SchemaErrorHandler errorHandler) { return prefix + (errorHandler.wereErrors() ? ":\n" + errorHandler.getErrorMessages() : ""); } private static class SchemaErrorHandler implements ErrorHandler { private final static Log LOG = LogFactory.getLog(XMLSchemaValidator.class); private StringBuffer errorMessages; public SchemaErrorHandler() { errorMessages = new StringBuffer(); } public void warning(SAXParseException exception) throws SAXException { LOG.warn(ExceptionUtil.exceptionToString(exception, true)); } public void error(SAXParseException exception) throws SAXException { String message = ExceptionUtil.exceptionToString(exception, true); LOG.error(message); errorMessages.append(message).append("\n"); } public void fatalError(SAXParseException exception) throws SAXException { String message = ExceptionUtil.exceptionToString(exception, true); LOG.fatal(message); errorMessages.append(message).append("\n"); } public boolean wereErrors() { return errorMessages.length() > 0; } public String getErrorMessages() { return errorMessages.toString(); } public void reset() { errorMessages = new StringBuffer(); } } }